[FFmpeg-soc] [soc]: r4446 - seek_api/mpeg.c
spyfeng
subversion at mplayerhq.hu
Sun Jun 14 18:39:19 CEST 2009
Author: spyfeng
Date: Sun Jun 14 18:39:19 2009
New Revision: 4446
Log:
fix some seek bugs and handle AVSEEK_FLAG_ANY.
still need more test.
Modified:
seek_api/mpeg.c
Modified: seek_api/mpeg.c
==============================================================================
--- seek_api/mpeg.c Sat Jun 13 12:20:11 2009 (r4445)
+++ seek_api/mpeg.c Sun Jun 14 18:39:19 2009 (r4446)
@@ -592,20 +592,21 @@ static int64_t mpegps_read_dts(AVFormatC
static int find_keyframe(AVFormatContext *s, int stream_index, int64_t *ret_pos, int64_t *pts, int64_t target_ts, int flags)
{
AVPacket pkt1, *pkt = &pkt1;
- int64_t pre_pts, pre_pos, size;
+ int64_t pre_pts = *pts, pre_pos = *ret_pos;
+ url_fseek(s->pb, *ret_pos, SEEK_SET);
for (;;) {
if (av_read_frame(s, pkt) < 0)
return -1;
- size = pkt->size;
av_free_packet(pkt);
if (!(pkt->flags & PKT_FLAG_KEY) || (stream_index != pkt->stream_index)) {
- *ret_pos += size;
- continue;
+ if (!(flags & AVSEEK_FLAG_ANY))
+ continue;
}
*pts = pkt->pts;
+ *ret_pos = pkt->pos;
if (*pts < target_ts) {
pre_pts = *pts;
@@ -614,7 +615,7 @@ static int find_keyframe(AVFormatContext
break;
}
- if (flags & AVSEEK_FLAG_BACKWARD && ((pre_pts + *pts)) >> 2 > target_ts) {
+ if (flags & AVSEEK_FLAG_BACKWARD && ((pre_pts + *pts) >> 2 > target_ts)) {
*ret_pos = pre_pts;
*pts = pre_pos;
}
@@ -626,12 +627,13 @@ static int mpegps_read_seek(struct AVFor
{
AVStream* st;
int index;
- int64_t pos, av_uninit(pos_min), av_uninit(pos_max), pos_limit;
+ int64_t pos, ret_pos, av_uninit(pos_min), av_uninit(pos_max), pos_limit;
int64_t ts_min, ts_max, ret_ts, pts;
if (min_ts > ts || max_ts < ts)
return -1;
-
+ if (ts < 0)
+ ts = 0;
if (stream_index < 0) {
stream_index= av_find_default_stream_index(s);
if(stream_index < 0)
@@ -641,12 +643,6 @@ static int mpegps_read_seek(struct AVFor
} else
st = s->streams[stream_index];
- if (ts < 0) {
- pts = ts = 0;
- url_fseek(s->pb, 0, SEEK_SET);
- goto success;
- }
-
if (st->discard >= AVDISCARD_ALL) {
av_log(s, AV_LOG_ERROR, "Not active stream!\n");
return -1;
@@ -660,30 +656,49 @@ static int mpegps_read_seek(struct AVFor
e = &st->index_entries[index];
pos = e->pos;
pts = e->timestamp;
- url_fseek(s->pb, pos, SEEK_SET);
av_log(s, AV_LOG_DEBUG, "the seek pos = %"PRId64", pts = %"PRId64", targe timestamp = %"PRId64"\n", pos, pts, ts);
- if (pts == ts) { // find the target timestamp
+ if (pts == ts || (ts < pts && index == 0)) { // find the target timestamp
+ url_fseek(s->pb, pos, SEEK_SET);
goto success;
}
+
+ if (flags & AVSEEK_FLAG_ANY) {
+
+ while(pts > ts) { // find the index timestamp smaller than target timestamp
+ index--;
+ pts = st->index_entries[index].timestamp;
+ pos = st->index_entries[index].pos;
+ }
+
+ if (find_keyframe(s, stream_index, &pos, &pts, ts, flags) == 0) {
+ url_fseek(s->pb, pos, SEEK_SET);
+ goto success;
+ } else {
+ return -1;
+ }
+ }
}
}
// search the scr use binary search
- ts_max=
- ts_min= AV_NOPTS_VALUE;
- pos_limit= -1;
- pos= av_gen_search(s, stream_index, ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags, &ret_ts, mpegps_read_dts);
+ ts_max =
+ ts_min = AV_NOPTS_VALUE;
+ pos_limit = -1;
+ if (flags & AVSEEK_FLAG_ANY) // add flag AVSEEK_FLAG_BACKWARD in order to get the smaller timestamp frame, then we can use av_read_frame() get next frame
+ ret_pos = av_gen_search(s, stream_index, ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags | AVSEEK_FLAG_BACKWARD, &ret_ts, mpegps_read_dts);
+ else
+ ret_pos = av_gen_search(s, stream_index, ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags, &ret_ts, mpegps_read_dts);
av_log(s, AV_LOG_DEBUG, "the seek pos = %"PRId64", ret_ts = %"PRId64"\n", pos, ret_ts);
- if(pos<0)
+ if (ret_pos<0)
return -1;
-
- url_fseek(s->pb, pos, SEEK_SET);
- if (find_keyframe(s, stream_index, &pos, &ret_ts, ts, flags) == 0) {
+ if (ret_ts < pts) { // in order to find the keyframe closer to target timestamp
+ pos = ret_pos;
+ pts = ret_ts;
+ }
+ if (find_keyframe(s, stream_index, &pos, &pts, ts, flags) == 0) {
url_fseek(s->pb, pos, SEEK_SET);
- pts = ret_ts;
goto success;
} else {
- av_update_cur_dts(s, st, ret_ts);
return -1;
}
success:
More information about the FFmpeg-soc
mailing list