Exemplo n.º 1
0
int libavsmash_video_find_first_valid_frame
(
    libavsmash_video_decode_handler_t *vdhp
)
{
    codec_configuration_t *config = &vdhp->config;
    for( uint32_t i = 1; i <= vdhp->sample_count + get_decoder_delay( config->ctx ); i++ )
    {
        AVPacket pkt = { 0 };
        get_sample( vdhp->root, vdhp->track_id, i, config, &pkt );
        av_frame_unref( vdhp->frame_buffer );
        int got_picture;
        if( decode_video_packet( config->ctx, vdhp->frame_buffer, &got_picture, &pkt ) >= 0 && got_picture )
        {
            vdhp->first_valid_frame_number = i - MIN( get_decoder_delay( config->ctx ), config->delay_count );
            if( vdhp->first_valid_frame_number > 1 || vdhp->sample_count == 1 )
            {
                vdhp->first_valid_frame = av_frame_clone( vdhp->frame_buffer );
                if( !vdhp->first_valid_frame )
                    return -1;
                av_frame_unref( vdhp->frame_buffer );
            }
            break;
        }
        else if( pkt.data )
            ++ config->delay_count;
    }
    return 0;
}
Exemplo n.º 2
0
static int get_picture
(
    libavsmash_video_decode_handler_t *vdhp,
    AVFrame                           *picture,
    uint32_t                           current,
    uint32_t                           goal
)
{
    codec_configuration_t *config = &vdhp->config;
    int got_picture = (current > goal);
    while( current <= goal )
    {
        int ret = decode_video_sample( vdhp, picture, &got_picture, current );
        if( ret == -1 )
            return -1;
        else if( ret == 1 )
            /* Sample doesn't exist. */
            break;
        ++current;
        if( config->update_pending )
            /* A new decoder configuration is needed. Anyway, stop getting picture. */
            break;
        if( !got_picture )
        {
            /* Fundamental seek operations after the decoder initialization is already done, but
             * more input samples are required to output and the goal become more distant. */
            ++ config->delay_count;
            ++ goal;
        }
    }
    /* Flush the last frames. */
    if( current > vdhp->sample_count && get_decoder_delay( config->ctx ) )
        while( current <= goal )
        {
            AVPacket pkt = { 0 };
            av_init_packet( &pkt );
            pkt.data = NULL;
            pkt.size = 0;
            av_frame_unref( picture );
            if( decode_video_packet( config->ctx, picture, &got_picture, &pkt ) < 0 )
            {
                lw_log_show( &config->lh, LW_LOG_WARNING, "Failed to decode and flush a video frame." );
                return -1;
            }
            ++current;
        }
    return got_picture ? 0 : -1;
}
Exemplo n.º 3
0
int lwlibav_find_first_valid_video_frame
(
    lwlibav_video_decode_handler_t *vdhp
)
{
    vdhp->movable_frame_buffer = av_frame_alloc();
    if( !vdhp->movable_frame_buffer )
        return -1;
    vdhp->av_seek_flags = (vdhp->lw_seek_flags & SEEK_POS_BASED) ? AVSEEK_FLAG_BYTE
                        : vdhp->lw_seek_flags == 0               ? AVSEEK_FLAG_FRAME
                        : 0;
    if( vdhp->frame_count != 1 )
    {
        vdhp->av_seek_flags |= AVSEEK_FLAG_BACKWARD;
        uint32_t rap_number;
        lwlibav_find_random_accessible_point( vdhp, 1, 0, &rap_number );
        int64_t rap_pos = lwlibav_get_random_accessible_point_position( vdhp, rap_number );
        if( av_seek_frame( vdhp->format, vdhp->stream_index, rap_pos, vdhp->av_seek_flags ) < 0 )
            av_seek_frame( vdhp->format, vdhp->stream_index, rap_pos, vdhp->av_seek_flags | AVSEEK_FLAG_ANY );
    }
    uint32_t decoder_delay = get_decoder_delay( vdhp->ctx );
    uint32_t thread_delay  = decoder_delay - vdhp->ctx->has_b_frames;
    AVPacket *pkt = &vdhp->packet;
    for( uint32_t i = 1; i <= vdhp->frame_count + vdhp->exh.delay_count; i++ )
    {
        lwlibav_get_av_frame( vdhp->format, vdhp->stream_index, i, pkt );
        av_frame_unref( vdhp->frame_buffer );
        int got_picture;
        int ret = avcodec_decode_video2( vdhp->ctx, vdhp->frame_buffer, &got_picture, pkt );
        /* Handle decoder delay derived from PAFF field coded pictures. */
        if( i <= vdhp->frame_count && i > decoder_delay
         && !got_picture && vdhp->frame_list[i].repeat_pict == 0 )
        {
            /* No output picture since the second field coded picture of the next frame is not decoded yet. */
            if( decoder_delay - thread_delay < 2 * vdhp->ctx->has_b_frames + 1UL )
                decoder_delay = thread_delay + 2 * vdhp->ctx->has_b_frames + 1UL;
        }
        if( ret >= 0 )
        {
            if( got_picture )
            {
                /* Found the first valid video frame. */
                vdhp->first_valid_frame_number = i - MIN( decoder_delay, vdhp->exh.delay_count );
                if( vdhp->first_valid_frame_number > 1 || vdhp->frame_count == 1 )
                {
                    vdhp->first_valid_frame = av_frame_clone( vdhp->frame_buffer );
                    if( !vdhp->first_valid_frame )
                        return -1;
                    av_frame_unref( vdhp->frame_buffer );
                }
                break;
            }
            else if( pkt->data )
                /* Output is delayed. */
                ++ vdhp->exh.delay_count;
            else
                /* No more output.
                 * Failed to find the first valid video frame. */
                return -1;
        }
    }
    return 0;
}
Exemplo n.º 4
0
/* This function returns the number of the next sample. */
static uint32_t seek_video
(
    libavsmash_video_decode_handler_t *vdhp,
    AVFrame                           *picture,
    uint32_t                           composition_sample_number,
    uint32_t                           rap_number,
    int                                error_ignorance
)
{
    /* Prepare to decode from random accessible sample. */
    codec_configuration_t *config = &vdhp->config;
    if( config->update_pending )
        /* Update the decoder configuration. */
        update_configuration( vdhp->root, vdhp->track_id, config );
    else
        libavsmash_flush_buffers( config );
    if( config->error )
        return 0;
    int got_picture;
    int output_ready = 0;
    uint64_t rap_cts = 0;
    uint32_t i;
    uint32_t decoder_delay = get_decoder_delay( config->ctx );
    uint32_t goal = composition_sample_number + decoder_delay;
    for( i = rap_number; i < goal; i++ )
    {
        if( config->index == config->queue.index )
            config->delay_count = MIN( decoder_delay, i - rap_number );
        int ret = decode_video_sample( vdhp, picture, &got_picture, i );
        if( got_picture )
        {
            output_ready = 1;
            if( decoder_delay > config->delay_count )
            {
                /* Shorten the distance to the goal if we got a frame earlier than expected. */
                uint32_t new_decoder_delay = config->delay_count;
                goal -= decoder_delay - new_decoder_delay;
                decoder_delay = new_decoder_delay;
            }
        }
        else if( output_ready )
        {
            /* More input samples are required to output and the goal become more distant. */
            ++decoder_delay;
            ++goal;
        }
        /* Some decoders return -1 when feeding a leading sample.
         * We don't consider as an error if the return value -1 is caused by a leading sample since it's not fatal at all. */
        if( i == vdhp->last_rap_number )
            rap_cts = picture->pts;
        if( ret == -1 && (uint64_t)picture->pts >= rap_cts && !error_ignorance )
        {
            lw_log_show( &config->lh, LW_LOG_WARNING, "Failed to decode a video frame." );
            return 0;
        }
        else if( ret >= 1 )
            /* No decoding occurs. */
            break;
    }
    if( config->index == config->queue.index )
        config->delay_count = MIN( decoder_delay, i - rap_number );
    return i;
}
Exemplo n.º 5
0
static uint32_t seek_video
(
    lwlibav_video_decode_handler_t *vdhp,
    AVFrame                        *picture,
    uint32_t                        presentation_sample_number,
    uint32_t                        rap_number,
    int64_t                         rap_pos,
    int                             error_ignorance
)
{
    /* Prepare to decode from random accessible sample. */
    lwlibav_extradata_handler_t *exhp = &vdhp->exh;
    int extradata_index = vdhp->frame_list[rap_number].extradata_index;
    if( extradata_index != exhp->current_index )
        /* Update the decoder configuration. */
        lwlibav_update_configuration( (lwlibav_decode_handler_t *)vdhp, rap_number, extradata_index, rap_pos );
    else
        lwlibav_flush_buffers( (lwlibav_decode_handler_t *)vdhp );
    if( vdhp->error )
        return 0;
    if( av_seek_frame( vdhp->format, vdhp->stream_index, rap_pos, vdhp->av_seek_flags ) < 0 )
        av_seek_frame( vdhp->format, vdhp->stream_index, rap_pos, vdhp->av_seek_flags | AVSEEK_FLAG_ANY );
    int      got_picture = 0;
    int64_t  rap_pts = AV_NOPTS_VALUE;
    uint32_t current;
    uint32_t decoder_delay = get_decoder_delay( vdhp->ctx );
    uint32_t thread_delay  = decoder_delay - vdhp->ctx->has_b_frames;
    uint32_t goal = presentation_sample_number + decoder_delay;
    exhp->delay_count     = 0;
    vdhp->last_half_frame = 0;
    for( current = rap_number; current <= goal; current++ )
    {
        int ret = decode_video_picture( vdhp, picture, &got_picture, &current, goal, rap_number );
        if( ret == -2 )
            return 0;
        else if( ret >= 1 )
        {
            /* No decoding occurs. */
            got_picture = 0;
            break;
        }
        /* Handle decoder delay derived from PAFF field coded pictures. */
        if( current <= vdhp->frame_count && current >= rap_number + decoder_delay
         && !got_picture && vdhp->frame_list[current].repeat_pict == 0 )
        {
            /* No output picture since the second field coded picture of the next frame is not decoded yet. */
            if( decoder_delay - thread_delay < 2 * vdhp->ctx->has_b_frames + 1UL )
            {
                uint32_t new_decoder_delay = thread_delay + 2 * vdhp->ctx->has_b_frames + 1UL;
                goal += new_decoder_delay - decoder_delay;
                decoder_delay = new_decoder_delay;
            }
        }
        if( got_picture )
        {
            exhp->delay_count = MIN( decoder_delay, current - rap_number );
            uint32_t frame_number = current - exhp->delay_count;
            vdhp->last_half_frame = (frame_number <= vdhp->frame_count && vdhp->frame_list[frame_number].repeat_pict == 0);
        }
        /* Some decoders return -1 when feeding a leading sample.
         * We don't consider as an error if the return value -1 is caused by a leading sample since it's not fatal at all. */
        if( current == vdhp->last_rap_number && picture->pts != AV_NOPTS_VALUE )
            rap_pts = picture->pts;
        if( ret == -1 && (picture->pts == AV_NOPTS_VALUE || picture->pts >= rap_pts) && !error_ignorance )
        {
            if( vdhp->lh.show_log )
                vdhp->lh.show_log( &vdhp->lh, LW_LOG_ERROR, "Failed to decode a video frame." );
            return 0;
        }
    }
    exhp->delay_count = MIN( decoder_delay, current - rap_number );
    if( current > rap_number && vdhp->last_half_frame )
    {
        if( got_picture )
            /* first field of PAFF field coded picture */
            vdhp->last_half_offset = 0;
        else
        {
            /* second field of PAFF field coded picture */
            vdhp->last_half_frame  = UINT32_MAX;
            vdhp->last_half_offset = 1;     /* A picture of the second field is already decoded. */
        }
    }
    else
    {
        vdhp->last_half_frame  = 0;
        vdhp->last_half_offset = 0;
    }
    return current;
}