- if ( position != this->video_expected || last_position < 0 )
- {
- if ( this->av_frame && position + 1 == this->video_expected )
- {
- // We're paused - use last image
- paused = 1;
- }
- else if ( !this->seekable && position > this->video_expected && ( position - this->video_expected ) < 250 )
- {
- // Fast forward - seeking is inefficient for small distances - just ignore following frames
- ignore = ( int )( ( position - this->video_expected ) / fps * source_fps );
- codec_context->skip_loop_filter = AVDISCARD_NONREF;
- }
- else if ( this->seekable && ( position < this->video_expected || position - this->video_expected >= 12 || last_position < 0 ) )
- {
- if ( use_new_seek && last_position == POSITION_INITIAL )
- {
- // find first key frame
- int ret = 0;
- int toscan = 100;
-
- while ( ret >= 0 && toscan-- > 0 )
- {
- ret = av_read_frame( context, &pkt );
- if ( ret >= 0 && ( pkt.flags & PKT_FLAG_KEY ) && pkt.stream_index == this->video_index )
- {
- mlt_log_verbose( MLT_PRODUCER_SERVICE(producer), "first_pts %lld dts %lld pts_dts_delta %d\n", pkt.pts, pkt.dts, (int)(pkt.pts - pkt.dts) );
- this->first_pts = pkt.pts;
- toscan = 0;
- }
- av_free_packet( &pkt );
- }
- // Rewind
- av_seek_frame( context, -1, 0, AVSEEK_FLAG_BACKWARD );
- }
-
- // Calculate the timestamp for the requested frame
- int64_t timestamp;
- if ( use_new_seek )
- {
- timestamp = ( req_position - 0.1 / source_fps ) /
- ( av_q2d( stream->time_base ) * source_fps );
- mlt_log_verbose( MLT_PRODUCER_SERVICE(producer), "pos %d pts %lld ", req_position, timestamp );
- if ( this->first_pts > 0 )
- timestamp += this->first_pts;
- else if ( context->start_time != AV_NOPTS_VALUE )
- timestamp += context->start_time;
- }
- else
- {
- timestamp = ( int64_t )( ( double )req_position / source_fps * AV_TIME_BASE + 0.5 );
- if ( context->start_time != AV_NOPTS_VALUE )
- timestamp += context->start_time;
- }
- if ( must_decode )
- timestamp -= AV_TIME_BASE;
- if ( timestamp < 0 )
- timestamp = 0;
- mlt_log_debug( MLT_PRODUCER_SERVICE(producer), "seeking timestamp %lld position %d expected %d last_pos %d\n",
- timestamp, position, this->video_expected, last_position );
-
- // Seek to the timestamp
- if ( use_new_seek )
- {
- codec_context->skip_loop_filter = AVDISCARD_NONREF;
- av_seek_frame( context, this->video_index, timestamp, AVSEEK_FLAG_BACKWARD );
- }
- else
- {
- av_seek_frame( context, -1, timestamp, AVSEEK_FLAG_BACKWARD );
- }
-
- // Remove the cached info relating to the previous position
- this->current_position = POSITION_INVALID;
- this->last_position = POSITION_INVALID;
- av_freep( &this->av_frame );