int CFfmpeg::Seek(int64_t pos) { int ret; double rate; int64_t seek_target; pthread_mutex_lock(&iolock); if(transcode) { rate = ((double)pos)/((double)filesize); seek_target = infmt_ctx->duration * rate; FFMPEG_DEBUG("rate=%f, target = %lld, duration=%lld", rate, seek_target, infmt_ctx->duration); int defaultStreamIndex = av_find_default_stream_index(infmt_ctx); seek_target = av_rescale_q(seek_target, AV_TIME_BASE_Q, infmt_ctx->streams[defaultStreamIndex]->time_base); ret = av_seek_frame(infmt_ctx, defaultStreamIndex, seek_target, AVSEEK_FLAG_ANY); FFMPEG_DEBUG("ret = %s", ret_str(ret)); eof= 0; if(curpos > pos) { if(vst) vdts_base = vst->cur_dts; if(ast1) a1dts_base = ast1->cur_dts; if(ast2) a2dts_base = ast2->cur_dts; } outputringbuffer.data_ptr = outputringbuffer.buffer_base; outputringbuffer.data_size = 0; } else { ret = fseek(m_pFp, pos, SEEK_SET); if(ret == 0) { curpos = pos; } FFMPEG_DEBUG("pos=%lld, m_nCurpos=%lld", pos, curpos); } pthread_mutex_unlock(&iolock); return 0; }
int ffsox_source_seek(source_t *n, int64_t ts) { AVStream *st; int si; if (0ll<ts) { si=av_find_default_stream_index(n->f.fc); st=n->f.fc->streams[si]; ts=av_rescale_q(ts,AV_TIME_BASE_Q,st->time_base); if (avformat_seek_file(n->f.fc,si,INT64_MIN,ts,INT64_MAX,0)<0) { DMESSAGE("seeking"); goto seek; } n->ts=av_rescale_q(st->cur_dts,st->time_base,AV_TIME_BASE_Q); } return 0; seek: return -1; }
static bool find_and_initialize_stream_decoders(struct ff_demuxer *demuxer) { AVFormatContext *format_context = demuxer->format_context; unsigned int i; AVStream *audio_stream = NULL; AVStream *video_stream = NULL; int64_t start_time = INT64_MAX; for (i = 0; i < format_context->nb_streams; i++) { AVCodecContext *codec = format_context->streams[i]->codec; if (codec->codec_type == AVMEDIA_TYPE_VIDEO && !video_stream) video_stream = format_context->streams[i]; if (codec->codec_type == AVMEDIA_TYPE_AUDIO && !audio_stream) audio_stream = format_context->streams[i]; } int default_stream_index = av_find_default_stream_index( demuxer->format_context); if (default_stream_index >= 0) { AVStream *stream = format_context->streams[default_stream_index]; if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) demuxer->clock.sync_type = AV_SYNC_AUDIO_MASTER; else if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) demuxer->clock.sync_type = AV_SYNC_VIDEO_MASTER; } if (video_stream != NULL) find_decoder(demuxer, video_stream); if (audio_stream != NULL) find_decoder(demuxer, audio_stream); if (demuxer->video_decoder == NULL && demuxer->audio_decoder == NULL) { return false; } if (!set_clock_sync_type(demuxer)) { return false; } for (i = 0; i < format_context->nb_streams; i++) { AVStream *st = format_context->streams[i]; int64_t st_start_time; if (st->discard == AVDISCARD_ALL || st->start_time == AV_NOPTS_VALUE) { continue; } st_start_time = av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q); start_time = FFMIN(start_time, st_start_time); } if (format_context->start_time != AV_NOPTS_VALUE) { if (start_time > format_context->start_time || start_time == INT64_MAX) { start_time = format_context->start_time; } } if (start_time != INT64_MAX) { set_decoder_start_time(demuxer->video_decoder, start_time); set_decoder_start_time(demuxer->audio_decoder, start_time); } if (demuxer->audio_decoder != NULL) { if (ff_callbacks_initialize(&demuxer->audio_callbacks)) { ff_decoder_start(demuxer->audio_decoder); } else { ff_decoder_free(demuxer->audio_decoder); demuxer->audio_decoder = NULL; if (!set_clock_sync_type(demuxer)) return false; } } if (demuxer->video_decoder != NULL) { if (ff_callbacks_initialize(&demuxer->video_callbacks)) { ff_decoder_start(demuxer->video_decoder); } else { ff_decoder_free(demuxer->video_decoder); demuxer->video_decoder = NULL; if (!set_clock_sync_type(demuxer)) return false; } } return set_clock_sync_type(demuxer); }
static int cmf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags) { av_log(NULL, AV_LOG_INFO, "\n------- cmf read_seek:BEGAN stream_index=%d ,sample_time=%lld,flags=%d --------\n\n", stream_index, sample_time, flags); struct cmf *cmf = s->priv_data; struct cmfvpb *ci = cmf->cmfvpb ; int ret; int64_t remain_seektime; int64_t seektimestamp; AVStream *st; av_log(NULL, AV_LOG_INFO, "cmf read_seek:TOTALINFO index[%lld] total_num [%lld] total_duration [%lld] \n",ci->cur_index,ci->total_num, ci->total_duration); av_log(NULL, AV_LOG_INFO, "cmf read_seek:SIZEINFO index[%lld] start_offset [0x%llx] end_offset [0x%llx] slice_size[0x%llx] \n", ci->cur_index, ci->start_offset, ci->end_offset, ci->size); av_log(NULL, AV_LOG_INFO, "cmf read_seek:TIMEINFO index[%lld] start_time [%lld]ms end_time [%lld]ms curslice_duration[%lld]ms \n", ci->cur_index, ci->start_time, ci->end_time, ci->curslice_duration); if(stream_index < 0){ stream_index= av_find_default_stream_index(s); if(stream_index < 0) return -1; } st= s->streams[stream_index]; seektimestamp=av_rescale_rnd(sample_time,st->time_base.num*1000,st->time_base.den,AV_ROUND_ZERO);//pts->ms av_log(s, AV_LOG_INFO, "cmf read_seek: checkin pts [%lld] seektimestamp[%lld]ms streamindex [%d]\n",sample_time,seektimestamp,stream_index); if ((seektimestamp >= ci->start_time)&&(seektimestamp <= ci->end_time )){ //in cur slice; av_log(s, AV_LOG_INFO, "cmf read_seek:IN CUR SLICE realtime = [%lld]ms start-end [%lld-%lld] calctoend[%lld]ms\n",seektimestamp,ci->start_time,ci->end_time,ci->end_time-seektimestamp); seektimestamp = seektimestamp - ci->start_time; seektimestamp = seektimestamp*1000;//ms->us av_log(NULL, AV_LOG_INFO, "cmf read_seek:index[%lld] curduration[%lld] seektimestamp[%lld]us\n", ci->cur_index, ci->curslice_duration,seektimestamp); ret = av_seek_frame(cmf->sctx, stream_index, seektimestamp, flags); if (ret < 0) { av_log(s, AV_LOG_INFO, "cmf read_seek:av_seek_frame Failed in cur slice\n"); } }else if ((seektimestamp < ci->start_time)||(seektimestamp > ci->end_time )){ av_log(s, AV_LOG_INFO, "cmf read_seek:OUT_CUR_SLICE firstcheck seektimestamp[%lld]ms start-end [%lld---%lld]ms\n",seektimestamp,ci->start_time,ci->end_time); //out of cur slice and in the total slice; //seek to cur slice; ret = url_fseekslicebytime(cmf->cmfvpb->pb,seektimestamp, AVSEEK_SLICE_BYTIME); if (ret < 0){ av_log(s, AV_LOG_INFO, "cmf read_seek: seekbytime error seektimestamp[%lld]ms\n",seektimestamp); return -1; } cmfvpb_getinfo(ci,AVCMD_SLICE_INDEX,0,&ci->cur_index); cmfvpb_getinfo(ci, AVCMD_SLICE_START_OFFSET, 0, &ci->start_offset); cmfvpb_getinfo(ci, AVCMD_SLICE_SIZE, 0 , &ci->size); cmfvpb_getinfo(ci, AVCMD_SLICE_STARTTIME, 0 , &ci->start_time); cmfvpb_getinfo(ci, AVCMD_SLICE_ENDTIME, 0 , &ci->end_time); ci->end_offset = ci->start_offset + ci->size; ci->curslice_duration=ci->end_time-ci->start_time; cmf->parsering_index = ci->cur_index; remain_seektime = seektimestamp - ci->start_time; cmf_flush_packet_queue(cmf->sctx); cmf_reset_packet(&cmf->pkt); av_log(s, AV_LOG_INFO, "cmf read_seek:OUT_CUR_SLICE switchtoincurindex index[%lld] seektimestamp[%lld]ms start-end [%lld--%lld]ms remainseektime[%lld]ms\n",ci->cur_index,seektimestamp,ci->start_time,ci->end_time,remain_seektime); ret = cmf_parser_next_slice(s, cmf->parsering_index, 0); if (ret>=0) { av_log(s, AV_LOG_INFO, "cmf read_seek:switchto incurindex index[%lld] seektimestamp[%lld]ms starttime[%lld]ms endtime[%lld]ms remainseektime[%lld]ms\n",ci->cur_index,seektimestamp,ci->start_time,ci->end_time,remain_seektime); //parser succeed,seek in cur slice; remain_seektime=remain_seektime*1000;//ms->us; av_log(s, AV_LOG_INFO, "cmf read_seek:switchto incurindex: index[%lld] remain_seektime[%lld]ms start-end [%lld - %lld]ms calctoend[%lld]\n",ci->cur_index,remain_seektime/1000,ci->start_time,ci->end_time,(ci->end_time-seektimestamp)); //seek to remainseektime; ret = av_seek_frame(cmf->sctx, stream_index, remain_seektime, flags); if (ret < 0) { av_log(s, AV_LOG_INFO, "cmf read_seek:out_curslice av_seek_frame Failed out of cur slice , cur_slice index [%lld]\n",ci->cur_index); return -1; } }else{ av_log(s, AV_LOG_INFO, "cmf parser_next_slice failed %s---%d [%d]\n",__FUNCTION__,__LINE__,ret); return -1; } }else if (seektimestamp > s->duration/1000){ av_log(s, AV_LOG_INFO, "cmf read_seek CMFSEEKERROR out of the total slice [%lld] [%lld]\n",seektimestamp,s->duration/1000); return -1; //out of total slice; }else { av_log(NULL, AV_LOG_INFO, "cmf read_seek CMFSEEKERROR index[%lld] start_time [%lld] end_time [%lld] curduration[%lld] seektimestamp[%lld]us\n", ci->cur_index, ci->start_time, ci->end_time, ci->curslice_duration,seektimestamp); return -1; } av_log(NULL, AV_LOG_INFO, "\n------cmf read_seek:END index[%lld] start_time [%lld]ms end_time [%lld]ms curslice_duration[%lld]ms -------\n\n", ci->cur_index, ci->start_time, ci->end_time, ci->curslice_duration); return 0; }