lavf: add missing new line to some error messages
[ffmpeg.git] / libavformat / nutdec.c
index 6d51950..397e44f 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include "libavutil/avstring.h"
+#include "libavutil/avassert.h"
 #include "libavutil/bswap.h"
 #include "libavutil/dict.h"
 #include "libavutil/mathematics.h"
 #include "avio_internal.h"
 #include "nut.h"
 
-#undef NDEBUG
-#include <assert.h>
-
 #define NUT_MAX_STREAMS 256    /* arbitrary sanity check value */
 
+static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index,
+                                  int64_t *pos_arg, int64_t pos_limit);
+
 static int get_str(AVIOContext *bc, char *string, unsigned int maxlen)
 {
     unsigned int len = ffio_read_varlen(bc);
@@ -298,23 +299,27 @@ static int decode_main_header(NUTContext *nut)
             nut->frame_code[i].header_idx     = tmp_head_idx;
         }
     }
-    assert(nut->frame_code['N'].flags == FLAG_INVALID);
+    av_assert0(nut->frame_code['N'].flags == FLAG_INVALID);
 
     if (end > avio_tell(bc) + 4) {
         int rem = 1024;
         GET_V(nut->header_count, tmp < 128U)
         nut->header_count++;
         for (i = 1; i < nut->header_count; i++) {
+            uint8_t *hdr;
             GET_V(nut->header_len[i], tmp > 0 && tmp < 256);
             rem -= nut->header_len[i];
             if (rem < 0) {
                 av_log(s, AV_LOG_ERROR, "invalid elision header\n");
                 return AVERROR_INVALIDDATA;
             }
-            nut->header[i] = av_malloc(nut->header_len[i]);
-            avio_read(bc, nut->header[i], nut->header_len[i]);
+            hdr = av_malloc(nut->header_len[i]);
+            if (!hdr)
+                return AVERROR(ENOMEM);
+            avio_read(bc, hdr, nut->header_len[i]);
+            nut->header[i] = hdr;
         }
-        assert(nut->header_len[0] == 0);
+        av_assert0(nut->header_len[0] == 0);
     }
 
     if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
@@ -375,7 +380,7 @@ static int decode_stream_header(NUTContext *nut)
         av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class);
         return -1;
     }
-    if (class < 3 && st->codec->codec_id == CODEC_ID_NONE)
+    if (class < 3 && st->codec->codec_id == AV_CODEC_ID_NONE)
         av_log(s, AV_LOG_ERROR,
                "Unknown codec tag '0x%04x' for stream number %d\n",
                (unsigned int) tmp, stream_id);
@@ -549,6 +554,25 @@ static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr)
     return 0;
 }
 
+//FIXME calculate exactly, this is just a good approximation.
+static int64_t find_duration(NUTContext *nut, int64_t filesize)
+{
+    AVFormatContext *s = nut->avf;
+    int64_t duration = 0;
+
+    int64_t pos = FFMAX(0, filesize - 2*nut->max_distance);
+    for(;;){
+        int64_t ts = nut_read_timestamp(s, -1, &pos, INT64_MAX);
+        if(ts < 0)
+            break;
+        duration = FFMAX(duration, ts);
+        pos++;
+    }
+    if(duration > 0)
+        s->duration_estimation_method = AVFMT_DURATION_FROM_PTS;
+    return duration;
+}
+
 static int find_and_decode_index(NUTContext *nut)
 {
     AVFormatContext *s = nut->avf;
@@ -560,10 +584,16 @@ static int find_and_decode_index(NUTContext *nut)
     int8_t *has_keyframe;
     int ret = -1;
 
+    if(filesize <= 0)
+        return -1;
+
     avio_seek(bc, filesize - 12, SEEK_SET);
     avio_seek(bc, filesize - avio_rb64(bc), SEEK_SET);
     if (avio_rb64(bc) != INDEX_STARTCODE) {
         av_log(s, AV_LOG_ERROR, "no index at the end\n");
+
+        if(s->duration<=0)
+            s->duration = find_duration(nut, filesize);
         return -1;
     }
 
@@ -593,7 +623,7 @@ static int find_and_decode_index(NUTContext *nut)
                 int flag = x & 1;
                 x >>= 1;
                 if (n + x >= syncpoint_count + 1) {
-                    av_log(s, AV_LOG_ERROR, "index overflow A\n");
+                    av_log(s, AV_LOG_ERROR, "index overflow A %d + %"PRIu64" >= %d\n", n, x, syncpoint_count + 1);
                     goto fail;
                 }
                 while (x--)
@@ -613,7 +643,7 @@ static int find_and_decode_index(NUTContext *nut)
                 av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n");
                 goto fail;
             }
-            assert(n <= syncpoint_count + 1);
+            av_assert0(n <= syncpoint_count + 1);
             for (; j < n && j < syncpoint_count; j++) {
                 if (has_keyframe[j]) {
                     uint64_t B, A = ffio_read_varlen(bc);
@@ -700,7 +730,7 @@ static int nut_read_header(AVFormatContext *s)
         find_and_decode_index(nut);
         avio_seek(bc, orig_pos, SEEK_SET);
     }
-    assert(nut->next_startcode == SYNCPOINT_STARTCODE);
+    av_assert0(nut->next_startcode == SYNCPOINT_STARTCODE);
 
     ff_metadata_conv_ctx(s, NULL, ff_nut_metadata_conv);
 
@@ -893,21 +923,18 @@ static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index,
     do {
         pos = find_startcode(bc, SYNCPOINT_STARTCODE, pos) + 1;
         if (pos < 1) {
-            assert(nut->next_startcode == 0);
             av_log(s, AV_LOG_ERROR, "read_timestamp failed.\n");
             return AV_NOPTS_VALUE;
         }
     } while (decode_syncpoint(nut, &pts, &back_ptr) < 0);
     *pos_arg = pos - 1;
-    assert(nut->last_syncpoint_pos == *pos_arg);
+    av_assert0(nut->last_syncpoint_pos == *pos_arg);
 
     av_log(s, AV_LOG_DEBUG, "return %"PRId64" %"PRId64"\n", pts, back_ptr);
-    if (stream_index == -1)
-        return pts;
-    else if (stream_index == -2)
+    if (stream_index == -2)
         return back_ptr;
-
-    assert(0);
+    av_assert0(stream_index == -1);
+    return pts;
 }
 
 static int read_seek(AVFormatContext *s, int stream_index,
@@ -924,6 +951,8 @@ static int read_seek(AVFormatContext *s, int stream_index,
     if (st->index_entries) {
         int index = av_index_search_timestamp(st, pts, flags);
         if (index < 0)
+            index = av_index_search_timestamp(st, pts, flags ^ AVSEEK_FLAG_BACKWARD);
+        if (index < 0)
             return -1;
 
         pos2 = st->index_entries[index].pos;
@@ -956,7 +985,7 @@ static int read_seek(AVFormatContext *s, int stream_index,
         sp = av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
                           NULL);
 
-        assert(sp);
+        av_assert0(sp);
         pos2 = sp->back_ptr - 15;
     }
     av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2);
@@ -985,10 +1014,10 @@ static int nut_read_close(AVFormatContext *s)
     return 0;
 }
 
-#if CONFIG_NUT_DEMUXER
 AVInputFormat ff_nut_demuxer = {
     .name           = "nut",
-    .long_name      = NULL_IF_CONFIG_SMALL("NUT format"),
+    .long_name      = NULL_IF_CONFIG_SMALL("NUT"),
+    .flags          = AVFMT_SEEK_TO_PTS,
     .priv_data_size = sizeof(NUTContext),
     .read_probe     = nut_probe,
     .read_header    = nut_read_header,
@@ -1001,4 +1030,3 @@ AVInputFormat ff_nut_demuxer = {
         ff_nut_subtitle_tags, 0
     },
 };
-#endif