diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2004-04-12 16:50:03 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2004-04-12 16:50:03 +0000 |
commit | 8d14a25c3efdb5de526db872ca7b29b63a530044 (patch) | |
tree | 22c484e1b7336e35e2318a29f0f2a248326ba076 /libavformat/asf.c | |
parent | ee77723580f6575b0778ded2bda46c91d07ffd4a (diff) | |
download | ffmpeg-8d14a25c3efdb5de526db872ca7b29b63a530044.tar.gz |
moving nearly identical binary search code from nut/mpeg/asf to utils.c
Originally committed as revision 3003 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/asf.c')
-rw-r--r-- | libavformat/asf.c | 120 |
1 files changed, 14 insertions, 106 deletions
diff --git a/libavformat/asf.c b/libavformat/asf.c index 19542e5a0c..b4088c9add 100644 --- a/libavformat/asf.c +++ b/libavformat/asf.c @@ -422,6 +422,8 @@ static int asf_get_packet(AVFormatContext *s) int rsize = 9; int c; + if((url_ftell(&s->pb) - s->data_offset) % asf->packet_size) + return -1; assert((url_ftell(&s->pb) - s->data_offset) % asf->packet_size == 0); c = get_byte(pb); @@ -705,7 +707,7 @@ static void asf_reset_header(AVFormatContext *s) asf->asf_st= NULL; } -static int64_t asf_read_pts(AVFormatContext *s, int64_t *ppos, int stream_index) +static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit) { ASFContext *asf = s->priv_data; AVPacket pkt1, *pkt = &pkt1; @@ -718,15 +720,19 @@ static int64_t asf_read_pts(AVFormatContext *s, int64_t *ppos, int stream_index) for(i=0; i<s->nb_streams; i++){ start_pos[i]= pos; } - + + pos= (pos+asf->packet_size-1-s->data_offset)/asf->packet_size*asf->packet_size+ s->data_offset; + *ppos= pos; + url_fseek(&s->pb, pos, SEEK_SET); + //printf("asf_read_pts\n"); - url_fseek(&s->pb, pos*asf->packet_size + s->data_offset, SEEK_SET); asf_reset_header(s); for(;;){ if (av_read_frame(s, pkt) < 0){ av_log(s, AV_LOG_INFO, "seek failed\n"); return AV_NOPTS_VALUE; } + pts= pkt->pts; av_free_packet(pkt); @@ -736,10 +742,10 @@ static int64_t asf_read_pts(AVFormatContext *s, int64_t *ppos, int stream_index) asf_st= s->streams[i]->priv_data; assert((asf_st->packet_pos - s->data_offset) % asf->packet_size == 0); - pos= (asf_st->packet_pos - s->data_offset) / asf->packet_size; + pos= asf_st->packet_pos; av_add_index_entry(s->streams[i], pos, pts, pos - start_pos[i] + 1, AVINDEX_KEYFRAME); - start_pos[i]= pos + 1; + start_pos[i]= asf_st->packet_pos + 1; if(pkt->stream_index == stream_index) break; @@ -755,112 +761,13 @@ static int64_t asf_read_pts(AVFormatContext *s, int64_t *ppos, int stream_index) static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts) { ASFContext *asf = s->priv_data; - AVStream *st; - int64_t pos; - int64_t pos_min, pos_max, pts_min, pts_max, cur_pts, pos_limit; - int no_change; - - if (stream_index == -1) - stream_index= av_find_default_stream_index(s); if (asf->packet_size <= 0) return -1; - pts_max= - pts_min= AV_NOPTS_VALUE; - pos_max= pos_limit= -1; // gcc thinks its uninitalized - - st= s->streams[stream_index]; - if(st->index_entries){ - AVIndexEntry *e; - int index; - - index= av_index_search_timestamp(st, pts); - e= &st->index_entries[index]; - if(e->timestamp <= pts){ - pos_min= e->pos; - pts_min= e->timestamp; -#ifdef DEBUG_SEEK - printf("unsing cached pos_min=0x%llx dts_min=%0.3f\n", - pos_min,pts_min / 90000.0); -#endif - }else{ - assert(index==0); - } - index++; - if(index < st->nb_index_entries){ - e= &st->index_entries[index]; - assert(e->timestamp >= pts); - pos_max= e->pos; - pts_max= e->timestamp; - pos_limit= pos_max - e->min_distance; -#ifdef DEBUG_SEEK - printf("unsing cached pos_max=0x%llx dts_max=%0.3f\n", - pos_max,pts_max / 90000.0); -#endif - } - } + if(av_seek_frame_binary(s, stream_index, pts)<0) + return -1; - if(pts_min == AV_NOPTS_VALUE){ - pos_min = 0; - pts_min = asf_read_pts(s, &pos_min, stream_index); - if (pts_min == AV_NOPTS_VALUE) return -1; - } - if(pts_max == AV_NOPTS_VALUE){ - pos_max = (url_filesize(url_fileno(&s->pb)) - 1 - s->data_offset) / asf->packet_size; //FIXME wrong - pts_max = s->duration; //FIXME wrong - pos_limit= pos_max; - } - - no_change=0; - while (pos_min < pos_limit) { - int64_t start_pos; - assert(pos_limit <= pos_max); - - if(no_change==0){ - int64_t approximate_keyframe_distance= pos_max - pos_limit; - // interpolate position (better than dichotomy) - pos = (int64_t)((double)(pos_max - pos_min) * - (double)(pts - pts_min) / - (double)(pts_max - pts_min)) + pos_min - approximate_keyframe_distance; - }else if(no_change==1){ - // bisection, if interpolation failed to change min or max pos last time - pos = (pos_min + pos_limit)>>1; - }else{ - // linear search if bisection failed, can only happen if there are very few or no keyframes between min/max - pos=pos_min; - } - if(pos <= pos_min) - pos= pos_min + 1; - else if(pos > pos_limit) - pos= pos_limit; - start_pos= pos; - - // read the next timestamp - cur_pts = asf_read_pts(s, &pos, stream_index); - if(pos == pos_max) - no_change++; - else - no_change=0; - -#ifdef DEBUG_SEEK -printf("%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%Ld\n", pos_min, pos, pos_max, pts_min, cur_pts, pts_max, pts, pos_limit, start_pos); -#endif - assert (cur_pts != AV_NOPTS_VALUE); - if (pts < cur_pts) { - pos_limit = start_pos - 1; - pos_max = pos; - pts_max = cur_pts; - } else { - pos_min = pos; - pts_min = cur_pts; - /* check if we are lucky */ - if (pts == cur_pts) - break; - } - } - pos = pos_min; - url_fseek(&s->pb, pos*asf->packet_size + s->data_offset, SEEK_SET); asf_reset_header(s); return 0; } @@ -874,6 +781,7 @@ static AVInputFormat asf_iformat = { asf_read_packet, asf_read_close, asf_read_seek, + asf_read_pts, }; #ifdef CONFIG_ENCODERS |