summaryrefslogtreecommitdiff
path: root/libavformat/nutdec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/nutdec.c')
-rw-r--r--libavformat/nutdec.c66
1 files changed, 45 insertions, 21 deletions
diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c
index da438ad127..f4813fe5ec 100644
--- a/libavformat/nutdec.c
+++ b/libavformat/nutdec.c
@@ -3,24 +3,25 @@
* Copyright (c) 2004-2006 Michael Niedermayer
* Copyright (c) 2003 Alex Beregszaszi
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/avstring.h"
+#include "libavutil/avassert.h"
#include "libavutil/bswap.h"
#include "libavutil/dict.h"
#include "libavutil/mathematics.h"
@@ -28,11 +29,11 @@
#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);
@@ -139,7 +140,7 @@ static uint64_t find_any_startcode(AVIOContext *bc, int64_t pos)
/* Note, this may fail if the stream is not seekable, but that should
* not matter, as in this case we simply start where we currently are */
avio_seek(bc, pos, SEEK_SET);
- while (!bc->eof_reached) {
+ while (!url_feof(bc)) {
state = (state << 8) | avio_r8(bc);
if ((state >> 56) != 'N')
continue;
@@ -298,7 +299,7 @@ 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;
@@ -318,7 +319,7 @@ static int decode_main_header(NUTContext *nut)
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)) {
@@ -553,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;
@@ -564,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;
}
@@ -617,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);
@@ -704,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);
@@ -843,7 +869,7 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
pos -= 8;
} else {
frame_code = avio_r8(bc);
- if (bc->eof_reached)
+ if (url_feof(bc))
return -1;
if (frame_code == 'N') {
tmp = frame_code;
@@ -897,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,
@@ -960,7 +983,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);
@@ -992,6 +1015,7 @@ static int nut_read_close(AVFormatContext *s)
AVInputFormat ff_nut_demuxer = {
.name = "nut",
.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,