Merge commit '81eec081afea9fc017a175581ceea7c420a0dfc3'
[ffmpeg.git] / libavformat / seek.c
index 758767e..bb5ca87 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <stdint.h>
+
 #include "seek.h"
+#include "libavutil/mathematics.h"
 #include "libavutil/mem.h"
+#include "internal.h"
 
 // NOTE: implementation should be moved here in another patch, to keep patches
 // separated.
-extern void av_read_frame_flush(AVFormatContext *s);
 
 /**
  * helper structure describing keyframe search state of one stream
@@ -47,38 +50,6 @@ typedef struct {
     int         terminated;  ///< termination flag for the current iteration
 } AVSyncPoint;
 
-/**
- * Compare two timestamps exactly, taking their respective time bases into account.
- *
- * @param ts_a timestamp A
- * @param tb_a time base for timestamp A
- * @param ts_b timestamp B
- * @param tb_b time base for timestamp A
- * @return -1, 0 or 1 if timestamp A is less than, equal or greater than timestamp B
- */
-static int compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
-{
-    int64_t a, b, res;
-
-    if (ts_a == INT64_MIN)
-        return ts_a < ts_b ? -1 : 0;
-    if (ts_a == INT64_MAX)
-        return ts_a > ts_b ?  1 : 0;
-    if (ts_b == INT64_MIN)
-        return ts_a > ts_b ?  1 : 0;
-    if (ts_b == INT64_MAX)
-        return ts_a < ts_b ? -1 : 0;
-
-    a = ts_a * tb_a.num * tb_b.den;
-    b = ts_b * tb_b.num * tb_a.den;
-
-    res = a - b;
-    if (!res)
-        return 0;
-    else
-        return (res >> 63) | 1;
-}
-
 /**
  * Compute a distance between timestamps.
  *
@@ -194,7 +165,7 @@ static void search_hi_lo_keyframes(AVFormatContext *s,
 
         // Evaluate key frames with known TS (or any frames, if AVSEEK_FLAG_ANY set).
         if (pts != AV_NOPTS_VALUE &&
-            ((flg & PKT_FLAG_KEY) || (flags & AVSEEK_FLAG_ANY))) {
+            ((flg & AV_PKT_FLAG_KEY) || (flags & AVSEEK_FLAG_ANY))) {
             if (flags & AVSEEK_FLAG_BYTE) {
                 // for byte seeking, use position as timestamp
                 ts        = pos;
@@ -216,7 +187,7 @@ static void search_hi_lo_keyframes(AVFormatContext *s,
             }
 
             if (sp->term_ts != AV_NOPTS_VALUE &&
-                compare_ts(ts, ts_tb, sp->term_ts, sp->term_ts_tb) > 0) {
+                av_compare_ts(ts, ts_tb, sp->term_ts, sp->term_ts_tb) > 0) {
                 // past the end position from last iteration, ignore packet
                 if (!sp->terminated) {
                     sp->terminated = 1;
@@ -233,7 +204,7 @@ static void search_hi_lo_keyframes(AVFormatContext *s,
                 continue;
             }
 
-            if (compare_ts(ts, ts_tb, timestamp, timebase) <= 0) {
+            if (av_compare_ts(ts, ts_tb, timestamp, timebase) <= 0) {
                 // keyframe found before target timestamp
                 if (sp->pos_lo == INT64_MAX) {
                     // found first keyframe lower than target timestamp
@@ -246,7 +217,7 @@ static void search_hi_lo_keyframes(AVFormatContext *s,
                     sp->pos_lo = pos;
                 }
             }
-            if (compare_ts(ts, ts_tb, timestamp, timebase) >= 0) {
+            if (av_compare_ts(ts, ts_tb, timestamp, timebase) >= 0) {
                 // keyframe found after target timestamp
                 if (sp->pos_hi == INT64_MAX) {
                     // found first keyframe higher than target timestamp
@@ -269,7 +240,7 @@ static void search_hi_lo_keyframes(AVFormatContext *s,
     }
 
     // Clean up the parser.
-    av_read_frame_flush(s);
+    ff_read_frame_flush(s);
 }
 
 int64_t ff_gen_syncpoint_search(AVFormatContext *s,
@@ -342,10 +313,10 @@ int64_t ff_gen_syncpoint_search(AVFormatContext *s,
 
     // Find keyframes in all active streams with timestamp/position just before
     // and just after requested timestamp/position.
-    step = 1024;
-    curpos = pos;
+    step = s->pb->buffer_size;
+    curpos = FFMAX(pos - step / 2, 0);
     for (;;) {
-        url_fseek(s->pb, curpos, SEEK_SET);
+        avio_seek(s->pb, curpos, SEEK_SET);
         search_hi_lo_keyframes(s,
                                ts, time_base,
                                flags,
@@ -391,15 +362,15 @@ int64_t ff_gen_syncpoint_search(AVFormatContext *s,
             min_distance = INT64_MAX;
             // Find timestamp closest to requested timestamp within min/max limits.
             if (sp->pos_lo != INT64_MAX
-                && compare_ts(ts_min, time_base, sp->ts_lo, st->time_base) <= 0
-                && compare_ts(sp->ts_lo, st->time_base, ts_max, time_base) <= 0) {
+                && av_compare_ts(ts_min, time_base, sp->ts_lo, st->time_base) <= 0
+                && av_compare_ts(sp->ts_lo, st->time_base, ts_max, time_base) <= 0) {
                 // low timestamp is in range
                 min_distance = ts_distance(ts, time_base, sp->ts_lo, st->time_base);
                 min_pos = sp->pos_lo;
             }
             if (sp->pos_hi != INT64_MAX
-                && compare_ts(ts_min, time_base, sp->ts_hi, st->time_base) <= 0
-                && compare_ts(sp->ts_hi, st->time_base, ts_max, time_base) <= 0) {
+                && av_compare_ts(ts_min, time_base, sp->ts_hi, st->time_base) <= 0
+                && av_compare_ts(sp->ts_hi, st->time_base, ts_max, time_base) <= 0) {
                 // high timestamp is in range, check distance
                 distance = ts_distance(sp->ts_hi, st->time_base, ts, time_base);
                 if (distance < min_distance) {
@@ -417,7 +388,7 @@ int64_t ff_gen_syncpoint_search(AVFormatContext *s,
         }
     }
 
-    url_fseek(s->pb, pos, SEEK_SET);
+    avio_seek(s->pb, pos, SEEK_SET);
     av_free(sync);
     return pos;
 }
@@ -437,16 +408,16 @@ AVParserState *ff_store_parser_state(AVFormatContext *s)
         return NULL;
     }
 
-    state->fpos = url_ftell(s->pb);
+    state->fpos = avio_tell(s->pb);
 
     // copy context structures
-    state->cur_st                           = s->cur_st;
     state->packet_buffer                    = s->packet_buffer;
+    state->parse_queue                      = s->parse_queue;
     state->raw_packet_buffer                = s->raw_packet_buffer;
     state->raw_packet_buffer_remaining_size = s->raw_packet_buffer_remaining_size;
 
-    s->cur_st                               = NULL;
     s->packet_buffer                        = NULL;
+    s->parse_queue                          = NULL;
     s->raw_packet_buffer                    = NULL;
     s->raw_packet_buffer_remaining_size     = RAW_PACKET_BUFFER_SIZE;
 
@@ -459,20 +430,12 @@ AVParserState *ff_store_parser_state(AVFormatContext *s)
         ss->parser        = st->parser;
         ss->last_IP_pts   = st->last_IP_pts;
         ss->cur_dts       = st->cur_dts;
-        ss->reference_dts = st->reference_dts;
-        ss->cur_ptr       = st->cur_ptr;
-        ss->cur_len       = st->cur_len;
         ss->probe_packets = st->probe_packets;
-        ss->cur_pkt       = st->cur_pkt;
 
         st->parser        = NULL;
         st->last_IP_pts   = AV_NOPTS_VALUE;
         st->cur_dts       = AV_NOPTS_VALUE;
-        st->reference_dts = AV_NOPTS_VALUE;
-        st->cur_ptr       = NULL;
-        st->cur_len       = 0;
         st->probe_packets = MAX_PROBE_PACKETS;
-        av_init_packet(&st->cur_pkt);
     }
 
     return state;
@@ -483,16 +446,16 @@ void ff_restore_parser_state(AVFormatContext *s, AVParserState *state)
     int i;
     AVStream *st;
     AVParserStreamState *ss;
-    av_read_frame_flush(s);
+    ff_read_frame_flush(s);
 
     if (!state)
         return;
 
-    url_fseek(s->pb, state->fpos, SEEK_SET);
+    avio_seek(s->pb, state->fpos, SEEK_SET);
 
     // copy context structures
-    s->cur_st                           = state->cur_st;
     s->packet_buffer                    = state->packet_buffer;
+    s->parse_queue                      = state->parse_queue;
     s->raw_packet_buffer                = state->raw_packet_buffer;
     s->raw_packet_buffer_remaining_size = state->raw_packet_buffer_remaining_size;
 
@@ -504,11 +467,7 @@ void ff_restore_parser_state(AVFormatContext *s, AVParserState *state)
         st->parser        = ss->parser;
         st->last_IP_pts   = ss->last_IP_pts;
         st->cur_dts       = ss->cur_dts;
-        st->reference_dts = ss->reference_dts;
-        st->cur_ptr       = ss->cur_ptr;
-        st->cur_len       = ss->cur_len;
         st->probe_packets = ss->probe_packets;
-        st->cur_pkt       = ss->cur_pkt;
     }
 
     av_free(state->stream_states);
@@ -538,13 +497,12 @@ void ff_free_parser_state(AVFormatContext *s, AVParserState *state)
         ss = &state->stream_states[i];
         if (ss->parser)
             av_parser_close(ss->parser);
-        av_free_packet(&ss->cur_pkt);
     }
 
     free_packet_list(state->packet_buffer);
+    free_packet_list(state->parse_queue);
     free_packet_list(state->raw_packet_buffer);
 
     av_free(state->stream_states);
     av_free(state);
 }
-