Statistics
| Branch: | Revision:

ffmpeg / libavformat / nutdec.c @ e356fc57

History | View | Annotate | Download (29.5 KB)

1 619d8e2e Michael Niedermayer
/*
2
 * "NUT" Container Format demuxer
3
 * Copyright (c) 2004-2006 Michael Niedermayer
4
 * Copyright (c) 2003 Alex Beregszaszi
5
 *
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22
23 00798e45 Aurelien Jacobs
#include <strings.h>
24 245976da Diego Biurrun
#include "libavutil/avstring.h"
25 6a5d31ac Diego Biurrun
#include "libavutil/bswap.h"
26 245976da Diego Biurrun
#include "libavutil/tree.h"
27 619d8e2e Michael Niedermayer
#include "nut.h"
28
29
#undef NDEBUG
30
#include <assert.h>
31
32 54036be1 Aurelien Jacobs
#if FF_API_MAX_STREAMS
33 3c0eec06 Aurelien Jacobs
#define NUT_MAX_STREAMS MAX_STREAMS
34
#else
35
#define NUT_MAX_STREAMS 256    /* arbitrary sanity check value */
36
#endif
37
38 ae628ec1 Anton Khirnov
static int get_str(AVIOContext *bc, char *string, unsigned int maxlen){
39 7798b42d Kostya Shishkov
    unsigned int len= ff_get_v(bc);
40 619d8e2e Michael Niedermayer
41
    if(len && maxlen)
42 b7effd4e Anton Khirnov
        avio_read(bc, string, FFMIN(len, maxlen));
43 619d8e2e Michael Niedermayer
    while(len > maxlen){
44 b7effd4e Anton Khirnov
        avio_r8(bc);
45 619d8e2e Michael Niedermayer
        len--;
46
    }
47
48
    if(maxlen)
49
        string[FFMIN(len, maxlen-1)]= 0;
50
51
    if(maxlen == len)
52
        return -1;
53
    else
54
        return 0;
55
}
56
57 ae628ec1 Anton Khirnov
static int64_t get_s(AVIOContext *bc){
58 7798b42d Kostya Shishkov
    int64_t v = ff_get_v(bc) + 1;
59 619d8e2e Michael Niedermayer
60
    if (v&1) return -(v>>1);
61
    else     return  (v>>1);
62
}
63
64 ae628ec1 Anton Khirnov
static uint64_t get_fourcc(AVIOContext *bc){
65 7798b42d Kostya Shishkov
    unsigned int len= ff_get_v(bc);
66 619d8e2e Michael Niedermayer
67 b7effd4e Anton Khirnov
    if     (len==2) return avio_rl16(bc);
68
    else if(len==4) return avio_rl32(bc);
69 619d8e2e Michael Niedermayer
    else            return -1;
70
}
71
72
#ifdef TRACE
73 ae628ec1 Anton Khirnov
static inline uint64_t get_v_trace(AVIOContext *bc, char *file, char *func, int line){
74 7798b42d Kostya Shishkov
    uint64_t v= ff_get_v(bc);
75 619d8e2e Michael Niedermayer
76 7a26da44 Michael Niedermayer
    av_log(NULL, AV_LOG_DEBUG, "get_v %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
77 619d8e2e Michael Niedermayer
    return v;
78
}
79
80 ae628ec1 Anton Khirnov
static inline int64_t get_s_trace(AVIOContext *bc, char *file, char *func, int line){
81 619d8e2e Michael Niedermayer
    int64_t v= get_s(bc);
82
83 7a26da44 Michael Niedermayer
    av_log(NULL, AV_LOG_DEBUG, "get_s %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
84 619d8e2e Michael Niedermayer
    return v;
85
}
86
87 ae628ec1 Anton Khirnov
static inline uint64_t get_vb_trace(AVIOContext *bc, char *file, char *func, int line){
88 619d8e2e Michael Niedermayer
    uint64_t v= get_vb(bc);
89
90 7a26da44 Michael Niedermayer
    av_log(NULL, AV_LOG_DEBUG, "get_vb %5"PRId64" / %"PRIX64" in %s %s:%d\n", v, v, file, func, line);
91 619d8e2e Michael Niedermayer
    return v;
92
}
93 7798b42d Kostya Shishkov
#define ff_get_v(bc)  get_v_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
94 619d8e2e Michael Niedermayer
#define get_s(bc)  get_s_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
95
#define get_vb(bc)  get_vb_trace(bc, __FILE__, __PRETTY_FUNCTION__, __LINE__)
96
#endif
97
98 ae628ec1 Anton Khirnov
static int get_packetheader(NUTContext *nut, AVIOContext *bc, int calculate_checksum, uint64_t startcode)
99 619d8e2e Michael Niedermayer
{
100 a47ec310 Diego Biurrun
    int64_t size;
101 619d8e2e Michael Niedermayer
//    start= url_ftell(bc) - 8;
102
103 8fc0162a Måns Rullgård
    startcode= av_be2ne64(startcode);
104 a07a06b0 Eli Friedman
    startcode= ff_crc04C11DB7_update(0, (uint8_t*)&startcode, 8);
105 073811cd Michael Niedermayer
106 992e78f5 Baptiste Coudurier
    init_checksum(bc, ff_crc04C11DB7_update, startcode);
107 7798b42d Kostya Shishkov
    size= ff_get_v(bc);
108 bb0eb714 Luca Barbato
    if(size > 4096)
109 b7effd4e Anton Khirnov
        avio_rb32(bc);
110 47772399 Michael Niedermayer
    if(get_checksum(bc) && size > 4096)
111
        return -1;
112 619d8e2e Michael Niedermayer
113 992e78f5 Baptiste Coudurier
    init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0);
114 619d8e2e Michael Niedermayer
115
    return size;
116
}
117
118 ae628ec1 Anton Khirnov
static uint64_t find_any_startcode(AVIOContext *bc, int64_t pos){
119 619d8e2e Michael Niedermayer
    uint64_t state=0;
120
121
    if(pos >= 0)
122 6b4aa5da Anton Khirnov
        avio_seek(bc, pos, SEEK_SET); //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
123 619d8e2e Michael Niedermayer
124
    while(!url_feof(bc)){
125 b7effd4e Anton Khirnov
        state= (state<<8) | avio_r8(bc);
126 619d8e2e Michael Niedermayer
        if((state>>56) != 'N')
127
            continue;
128
        switch(state){
129
        case MAIN_STARTCODE:
130
        case STREAM_STARTCODE:
131
        case SYNCPOINT_STARTCODE:
132
        case INFO_STARTCODE:
133
        case INDEX_STARTCODE:
134
            return state;
135
        }
136
    }
137
138
    return 0;
139
}
140
141
/**
142 93951943 Diego Biurrun
 * Find the given startcode.
143 619d8e2e Michael Niedermayer
 * @param code the startcode
144
 * @param pos the start position of the search, or -1 if the current position
145 32e543f8 Benoit Fouet
 * @return the position of the startcode or -1 if not found
146 619d8e2e Michael Niedermayer
 */
147 ae628ec1 Anton Khirnov
static int64_t find_startcode(AVIOContext *bc, uint64_t code, int64_t pos){
148 619d8e2e Michael Niedermayer
    for(;;){
149
        uint64_t startcode= find_any_startcode(bc, pos);
150
        if(startcode == code)
151
            return url_ftell(bc) - 8;
152
        else if(startcode == 0)
153
            return -1;
154
        pos=-1;
155
    }
156
}
157
158
static int nut_probe(AVProbeData *p){
159
    int i;
160
    uint64_t code= 0;
161
162
    for (i = 0; i < p->buf_size; i++) {
163
        code = (code << 8) | p->buf[i];
164
        if (code == MAIN_STARTCODE)
165
            return AVPROBE_SCORE_MAX;
166
    }
167
    return 0;
168
}
169
170
#define GET_V(dst, check) \
171 7798b42d Kostya Shishkov
    tmp= ff_get_v(bc);\
172 619d8e2e Michael Niedermayer
    if(!(check)){\
173
        av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp);\
174
        return -1;\
175
    }\
176
    dst= tmp;
177
178 ae628ec1 Anton Khirnov
static int skip_reserved(AVIOContext *bc, int64_t pos){
179 619d8e2e Michael Niedermayer
    pos -= url_ftell(bc);
180
    if(pos<0){
181 6b4aa5da Anton Khirnov
        avio_seek(bc, pos, SEEK_CUR);
182 619d8e2e Michael Niedermayer
        return -1;
183
    }else{
184
        while(pos--)
185 b7effd4e Anton Khirnov
            avio_r8(bc);
186 619d8e2e Michael Niedermayer
        return 0;
187
    }
188
}
189
190
static int decode_main_header(NUTContext *nut){
191
    AVFormatContext *s= nut->avf;
192 ae628ec1 Anton Khirnov
    AVIOContext *bc = s->pb;
193 619d8e2e Michael Niedermayer
    uint64_t tmp, end;
194
    unsigned int stream_count;
195 3b4f69ae Michael Niedermayer
    int i, j, tmp_stream, tmp_mul, tmp_pts, tmp_size, count, tmp_res, tmp_head_idx;
196 6cb4b28f Michael Niedermayer
    int64_t tmp_match;
197 619d8e2e Michael Niedermayer
198 073811cd Michael Niedermayer
    end= get_packetheader(nut, bc, 1, MAIN_STARTCODE);
199 5d97d9d5 Michael Niedermayer
    end += url_ftell(bc);
200 619d8e2e Michael Niedermayer
201
    GET_V(tmp              , tmp >=2 && tmp <= 3)
202 3c0eec06 Aurelien Jacobs
    GET_V(stream_count     , tmp > 0 && tmp <= NUT_MAX_STREAMS)
203 619d8e2e Michael Niedermayer
204 7798b42d Kostya Shishkov
    nut->max_distance = ff_get_v(bc);
205 619d8e2e Michael Niedermayer
    if(nut->max_distance > 65536){
206
        av_log(s, AV_LOG_DEBUG, "max_distance %d\n", nut->max_distance);
207
        nut->max_distance= 65536;
208
    }
209
210
    GET_V(nut->time_base_count, tmp>0 && tmp<INT_MAX / sizeof(AVRational))
211
    nut->time_base= av_malloc(nut->time_base_count * sizeof(AVRational));
212
213
    for(i=0; i<nut->time_base_count; i++){
214
        GET_V(nut->time_base[i].num, tmp>0 && tmp<(1ULL<<31))
215
        GET_V(nut->time_base[i].den, tmp>0 && tmp<(1ULL<<31))
216 9ce6c138 Aurelien Jacobs
        if(av_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1){
217 619d8e2e Michael Niedermayer
            av_log(s, AV_LOG_ERROR, "time base invalid\n");
218 0d3ee135 Stefano Sabatini
            return AVERROR_INVALIDDATA;
219 619d8e2e Michael Niedermayer
        }
220
    }
221
    tmp_pts=0;
222
    tmp_mul=1;
223
    tmp_stream=0;
224 6cb4b28f Michael Niedermayer
    tmp_match= 1-(1LL<<62);
225 3b4f69ae Michael Niedermayer
    tmp_head_idx= 0;
226 619d8e2e Michael Niedermayer
    for(i=0; i<256;){
227 7798b42d Kostya Shishkov
        int tmp_flags = ff_get_v(bc);
228
        int tmp_fields= ff_get_v(bc);
229 619d8e2e Michael Niedermayer
        if(tmp_fields>0) tmp_pts   = get_s(bc);
230 7798b42d Kostya Shishkov
        if(tmp_fields>1) tmp_mul   = ff_get_v(bc);
231
        if(tmp_fields>2) tmp_stream= ff_get_v(bc);
232
        if(tmp_fields>3) tmp_size  = ff_get_v(bc);
233 619d8e2e Michael Niedermayer
        else             tmp_size  = 0;
234 7798b42d Kostya Shishkov
        if(tmp_fields>4) tmp_res   = ff_get_v(bc);
235 619d8e2e Michael Niedermayer
        else             tmp_res   = 0;
236 7798b42d Kostya Shishkov
        if(tmp_fields>5) count     = ff_get_v(bc);
237 619d8e2e Michael Niedermayer
        else             count     = tmp_mul - tmp_size;
238 6cb4b28f Michael Niedermayer
        if(tmp_fields>6) tmp_match = get_s(bc);
239 3b4f69ae Michael Niedermayer
        if(tmp_fields>7) tmp_head_idx= ff_get_v(bc);
240 619d8e2e Michael Niedermayer
241 3b4f69ae Michael Niedermayer
        while(tmp_fields-- > 8)
242 7798b42d Kostya Shishkov
           ff_get_v(bc);
243 619d8e2e Michael Niedermayer
244
        if(count == 0 || i+count > 256){
245
            av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i);
246 0d3ee135 Stefano Sabatini
            return AVERROR_INVALIDDATA;
247 619d8e2e Michael Niedermayer
        }
248
        if(tmp_stream >= stream_count){
249
            av_log(s, AV_LOG_ERROR, "illegal stream number\n");
250 0d3ee135 Stefano Sabatini
            return AVERROR_INVALIDDATA;
251 619d8e2e Michael Niedermayer
        }
252
253
        for(j=0; j<count; j++,i++){
254
            if (i == 'N') {
255
                nut->frame_code[i].flags= FLAG_INVALID;
256
                j--;
257
                continue;
258
            }
259
            nut->frame_code[i].flags           = tmp_flags ;
260
            nut->frame_code[i].pts_delta       = tmp_pts   ;
261
            nut->frame_code[i].stream_id       = tmp_stream;
262
            nut->frame_code[i].size_mul        = tmp_mul   ;
263
            nut->frame_code[i].size_lsb        = tmp_size+j;
264
            nut->frame_code[i].reserved_count  = tmp_res   ;
265 3b4f69ae Michael Niedermayer
            nut->frame_code[i].header_idx      = tmp_head_idx;
266 619d8e2e Michael Niedermayer
        }
267
    }
268
    assert(nut->frame_code['N'].flags == FLAG_INVALID);
269
270 3b4f69ae Michael Niedermayer
    if(end > url_ftell(bc) + 4){
271
        int rem= 1024;
272
        GET_V(nut->header_count, tmp<128U)
273
        nut->header_count++;
274
        for(i=1; i<nut->header_count; i++){
275
            GET_V(nut->header_len[i], tmp>0 && tmp<256);
276
            rem -= nut->header_len[i];
277
            if(rem < 0){
278
                av_log(s, AV_LOG_ERROR, "invalid elision header\n");
279 0d3ee135 Stefano Sabatini
                return AVERROR_INVALIDDATA;
280 3b4f69ae Michael Niedermayer
            }
281
            nut->header[i]= av_malloc(nut->header_len[i]);
282 b7effd4e Anton Khirnov
            avio_read(bc, nut->header[i], nut->header_len[i]);
283 3b4f69ae Michael Niedermayer
        }
284
        assert(nut->header_len[0]==0);
285
    }
286
287 5d97d9d5 Michael Niedermayer
    if(skip_reserved(bc, end) || get_checksum(bc)){
288 93951943 Diego Biurrun
        av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n");
289 0d3ee135 Stefano Sabatini
        return AVERROR_INVALIDDATA;
290 619d8e2e Michael Niedermayer
    }
291
292
    nut->stream = av_mallocz(sizeof(StreamContext)*stream_count);
293
    for(i=0; i<stream_count; i++){
294
        av_new_stream(s, i);
295
    }
296
297
    return 0;
298
}
299
300
static int decode_stream_header(NUTContext *nut){
301
    AVFormatContext *s= nut->avf;
302 ae628ec1 Anton Khirnov
    AVIOContext *bc = s->pb;
303 619d8e2e Michael Niedermayer
    StreamContext *stc;
304 c873bc17 Michael Niedermayer
    int class, stream_id;
305 619d8e2e Michael Niedermayer
    uint64_t tmp, end;
306
    AVStream *st;
307
308 073811cd Michael Niedermayer
    end= get_packetheader(nut, bc, 1, STREAM_STARTCODE);
309 5d97d9d5 Michael Niedermayer
    end += url_ftell(bc);
310 619d8e2e Michael Niedermayer
311 efd8f22a Michael Niedermayer
    GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base);
312 619d8e2e Michael Niedermayer
    stc= &nut->stream[stream_id];
313
314
    st = s->streams[stream_id];
315
    if (!st)
316 769e10f0 Panagiotis Issaris
        return AVERROR(ENOMEM);
317 619d8e2e Michael Niedermayer
318 7798b42d Kostya Shishkov
    class = ff_get_v(bc);
319 619d8e2e Michael Niedermayer
    tmp = get_fourcc(bc);
320
    st->codec->codec_tag= tmp;
321
    switch(class)
322
    {
323
        case 0:
324 72415b2a Stefano Sabatini
            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
325 49837b8d Stefano Sabatini
            st->codec->codec_id = av_codec_get_id(
326
                (const AVCodecTag * const []) { ff_codec_bmp_tags, ff_nut_video_tags, 0 },
327
                tmp);
328 619d8e2e Michael Niedermayer
            break;
329
        case 1:
330 72415b2a Stefano Sabatini
            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
331 1a40491e Daniel Verkamp
            st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, tmp);
332 619d8e2e Michael Niedermayer
            break;
333
        case 2:
334 72415b2a Stefano Sabatini
            st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
335 1a40491e Daniel Verkamp
            st->codec->codec_id = ff_codec_get_id(ff_nut_subtitle_tags, tmp);
336 a048febd Michael Niedermayer
            break;
337 619d8e2e Michael Niedermayer
        case 3:
338 72415b2a Stefano Sabatini
            st->codec->codec_type = AVMEDIA_TYPE_DATA;
339 619d8e2e Michael Niedermayer
            break;
340
        default:
341 93951943 Diego Biurrun
            av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class);
342 619d8e2e Michael Niedermayer
            return -1;
343
    }
344 9fdfd21c Michael Niedermayer
    if(class<3 && st->codec->codec_id == CODEC_ID_NONE)
345 8e89cd1f Stefano Sabatini
        av_log(s, AV_LOG_ERROR, "Unknown codec tag '0x%04x' for stream number %d\n",
346
               (unsigned int)tmp, stream_id);
347 9fdfd21c Michael Niedermayer
348 619d8e2e Michael Niedermayer
    GET_V(stc->time_base_id    , tmp < nut->time_base_count);
349
    GET_V(stc->msb_pts_shift   , tmp < 16);
350 7798b42d Kostya Shishkov
    stc->max_pts_distance= ff_get_v(bc);
351 93951943 Diego Biurrun
    GET_V(stc->decode_delay    , tmp < 1000); //sanity limit, raise this if Moore's law is true
352 619d8e2e Michael Niedermayer
    st->codec->has_b_frames= stc->decode_delay;
353 7798b42d Kostya Shishkov
    ff_get_v(bc); //stream flags
354 619d8e2e Michael Niedermayer
355
    GET_V(st->codec->extradata_size, tmp < (1<<30));
356
    if(st->codec->extradata_size){
357
        st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
358 b7effd4e Anton Khirnov
        avio_read(bc, st->codec->extradata, st->codec->extradata_size);
359 619d8e2e Michael Niedermayer
    }
360
361 72415b2a Stefano Sabatini
    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
362 619d8e2e Michael Niedermayer
        GET_V(st->codec->width , tmp > 0)
363
        GET_V(st->codec->height, tmp > 0)
364 59729451 Aurelien Jacobs
        st->sample_aspect_ratio.num= ff_get_v(bc);
365
        st->sample_aspect_ratio.den= ff_get_v(bc);
366
        if((!st->sample_aspect_ratio.num) != (!st->sample_aspect_ratio.den)){
367
            av_log(s, AV_LOG_ERROR, "invalid aspect ratio %d/%d\n", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
368 619d8e2e Michael Niedermayer
            return -1;
369
        }
370 7798b42d Kostya Shishkov
        ff_get_v(bc); /* csp type */
371 72415b2a Stefano Sabatini
    }else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
372 619d8e2e Michael Niedermayer
        GET_V(st->codec->sample_rate , tmp > 0)
373 eae213af Oded Shimon
        ff_get_v(bc); // samplerate_den
374 619d8e2e Michael Niedermayer
        GET_V(st->codec->channels, tmp > 0)
375
    }
376 5d97d9d5 Michael Niedermayer
    if(skip_reserved(bc, end) || get_checksum(bc)){
377 93951943 Diego Biurrun
        av_log(s, AV_LOG_ERROR, "stream header %d checksum mismatch\n", stream_id);
378 619d8e2e Michael Niedermayer
        return -1;
379
    }
380 efd8f22a Michael Niedermayer
    stc->time_base= &nut->time_base[stc->time_base_id];
381
    av_set_pts_info(s->streams[stream_id], 63, stc->time_base->num, stc->time_base->den);
382 619d8e2e Michael Niedermayer
    return 0;
383
}
384
385 90c2295b Evgeniy Stepanov
static void set_disposition_bits(AVFormatContext* avf, char* value, int stream_id){
386
    int flag = 0, i;
387
    for (i=0; ff_nut_dispositions[i].flag; ++i) {
388
        if (!strcmp(ff_nut_dispositions[i].str, value))
389
            flag = ff_nut_dispositions[i].flag;
390
    }
391
    if (!flag)
392
        av_log(avf, AV_LOG_INFO, "unknown disposition type '%s'\n", value);
393
    for (i = 0; i < avf->nb_streams; ++i)
394
        if (stream_id == i || stream_id == -1)
395
            avf->streams[i]->disposition |= flag;
396
}
397
398 619d8e2e Michael Niedermayer
static int decode_info_header(NUTContext *nut){
399
    AVFormatContext *s= nut->avf;
400 ae628ec1 Anton Khirnov
    AVIOContext *bc = s->pb;
401 e1c0b00b Anton Khirnov
    uint64_t tmp, chapter_start, chapter_len;
402
    unsigned int stream_id_plus1, count;
403 619d8e2e Michael Niedermayer
    int chapter_id, i;
404
    int64_t value, end;
405 7ebab679 Michael Niedermayer
    char name[256], str_value[1024], type_str[256];
406 0fca8bc8 Michael Niedermayer
    const char *type;
407 883fe4d5 Michael Niedermayer
    AVChapter *chapter= NULL;
408 00798e45 Aurelien Jacobs
    AVStream *st= NULL;
409 c55f891c Anton Khirnov
    AVMetadata **metadata = NULL;
410 619d8e2e Michael Niedermayer
411 073811cd Michael Niedermayer
    end= get_packetheader(nut, bc, 1, INFO_STARTCODE);
412 5d97d9d5 Michael Niedermayer
    end += url_ftell(bc);
413 619d8e2e Michael Niedermayer
414
    GET_V(stream_id_plus1, tmp <= s->nb_streams)
415
    chapter_id   = get_s(bc);
416 7798b42d Kostya Shishkov
    chapter_start= ff_get_v(bc);
417
    chapter_len  = ff_get_v(bc);
418
    count        = ff_get_v(bc);
419 883fe4d5 Michael Niedermayer
420
    if(chapter_id && !stream_id_plus1){
421
        int64_t start= chapter_start / nut->time_base_count;
422 abd2256d Michael Niedermayer
        chapter= ff_new_chapter(s, chapter_id,
423
                                nut->time_base[chapter_start % nut->time_base_count],
424
                                start, start + chapter_len, NULL);
425 c55f891c Anton Khirnov
        metadata = &chapter->metadata;
426
    } else if(stream_id_plus1) {
427 00798e45 Aurelien Jacobs
        st= s->streams[stream_id_plus1 - 1];
428 c55f891c Anton Khirnov
        metadata = &st->metadata;
429
    } else
430
        metadata = &s->metadata;
431 883fe4d5 Michael Niedermayer
432 619d8e2e Michael Niedermayer
    for(i=0; i<count; i++){
433
        get_str(bc, name, sizeof(name));
434
        value= get_s(bc);
435
        if(value == -1){
436
            type= "UTF-8";
437
            get_str(bc, str_value, sizeof(str_value));
438
        }else if(value == -2){
439 0fca8bc8 Michael Niedermayer
            get_str(bc, type_str, sizeof(type_str));
440
            type= type_str;
441 619d8e2e Michael Niedermayer
            get_str(bc, str_value, sizeof(str_value));
442
        }else if(value == -3){
443
            type= "s";
444
            value= get_s(bc);
445
        }else if(value == -4){
446
            type= "t";
447 7798b42d Kostya Shishkov
            value= ff_get_v(bc);
448 619d8e2e Michael Niedermayer
        }else if(value < -4){
449
            type= "r";
450
            get_s(bc);
451
        }else{
452
            type= "v";
453
        }
454
455 d6f142a1 Diego Pettenò
        if (stream_id_plus1 > s->nb_streams) {
456 90c2295b Evgeniy Stepanov
            av_log(s, AV_LOG_ERROR, "invalid stream id for info packet\n");
457
            continue;
458
        }
459
460 00798e45 Aurelien Jacobs
        if(!strcmp(type, "UTF-8")){
461 c55f891c Anton Khirnov
            if(chapter_id==0 && !strcmp(name, "Disposition")) {
462 90c2295b Evgeniy Stepanov
                set_disposition_bits(s, str_value, stream_id_plus1 - 1);
463 c55f891c Anton Khirnov
                continue;
464
            }
465 00798e45 Aurelien Jacobs
            if(metadata && strcasecmp(name,"Uses")
466
               && strcasecmp(name,"Depends") && strcasecmp(name,"Replaces"))
467 2ef6c124 Stefano Sabatini
                av_metadata_set2(metadata, name, str_value, 0);
468 883fe4d5 Michael Niedermayer
        }
469 619d8e2e Michael Niedermayer
    }
470
471 5d97d9d5 Michael Niedermayer
    if(skip_reserved(bc, end) || get_checksum(bc)){
472 93951943 Diego Biurrun
        av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n");
473 619d8e2e Michael Niedermayer
        return -1;
474
    }
475
    return 0;
476
}
477
478 4d5be986 Michael Niedermayer
static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr){
479 619d8e2e Michael Niedermayer
    AVFormatContext *s= nut->avf;
480 ae628ec1 Anton Khirnov
    AVIOContext *bc = s->pb;
481 4d5be986 Michael Niedermayer
    int64_t end, tmp;
482 619d8e2e Michael Niedermayer
483 faf7cbf1 Michael Niedermayer
    nut->last_syncpoint_pos= url_ftell(bc)-8;
484 619d8e2e Michael Niedermayer
485 073811cd Michael Niedermayer
    end= get_packetheader(nut, bc, 1, SYNCPOINT_STARTCODE);
486 5d97d9d5 Michael Niedermayer
    end += url_ftell(bc);
487 619d8e2e Michael Niedermayer
488 7798b42d Kostya Shishkov
    tmp= ff_get_v(bc);
489
    *back_ptr= nut->last_syncpoint_pos - 16*ff_get_v(bc);
490 4d5be986 Michael Niedermayer
    if(*back_ptr < 0)
491
        return -1;
492 619d8e2e Michael Niedermayer
493 103d74ea Oded Shimon
    ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count], tmp / nut->time_base_count);
494 619d8e2e Michael Niedermayer
495 5d97d9d5 Michael Niedermayer
    if(skip_reserved(bc, end) || get_checksum(bc)){
496 faf7cbf1 Michael Niedermayer
        av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n");
497 619d8e2e Michael Niedermayer
        return -1;
498
    }
499 4d5be986 Michael Niedermayer
500
    *ts= tmp / s->nb_streams * av_q2d(nut->time_base[tmp % s->nb_streams])*AV_TIME_BASE;
501 4a3b5fe1 Michael Niedermayer
    ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts);
502 4d5be986 Michael Niedermayer
503 619d8e2e Michael Niedermayer
    return 0;
504
}
505
506 e8272029 Michael Niedermayer
static int find_and_decode_index(NUTContext *nut){
507
    AVFormatContext *s= nut->avf;
508 ae628ec1 Anton Khirnov
    AVIOContext *bc = s->pb;
509 e8272029 Michael Niedermayer
    uint64_t tmp, end;
510
    int i, j, syncpoint_count;
511
    int64_t filesize= url_fsize(bc);
512
    int64_t *syncpoints;
513
    int8_t *has_keyframe;
514 c2a3dcaf Michael Niedermayer
    int ret= -1;
515 e8272029 Michael Niedermayer
516 6b4aa5da Anton Khirnov
    avio_seek(bc, filesize-12, SEEK_SET);
517
    avio_seek(bc, filesize-avio_rb64(bc), SEEK_SET);
518 b7effd4e Anton Khirnov
    if(avio_rb64(bc) != INDEX_STARTCODE){
519 e8272029 Michael Niedermayer
        av_log(s, AV_LOG_ERROR, "no index at the end\n");
520
        return -1;
521
    }
522
523 073811cd Michael Niedermayer
    end= get_packetheader(nut, bc, 1, INDEX_STARTCODE);
524 5d97d9d5 Michael Niedermayer
    end += url_ftell(bc);
525 e8272029 Michael Niedermayer
526 7798b42d Kostya Shishkov
    ff_get_v(bc); //max_pts
527 e8272029 Michael Niedermayer
    GET_V(syncpoint_count, tmp < INT_MAX/8 && tmp > 0)
528
    syncpoints= av_malloc(sizeof(int64_t)*syncpoint_count);
529
    has_keyframe= av_malloc(sizeof(int8_t)*(syncpoint_count+1));
530
    for(i=0; i<syncpoint_count; i++){
531 c2a3dcaf Michael Niedermayer
        syncpoints[i] = ff_get_v(bc);
532
        if(syncpoints[i] <= 0)
533
            goto fail;
534 e8272029 Michael Niedermayer
        if(i)
535
            syncpoints[i] += syncpoints[i-1];
536
    }
537
538
    for(i=0; i<s->nb_streams; i++){
539
        int64_t last_pts= -1;
540
        for(j=0; j<syncpoint_count;){
541 7798b42d Kostya Shishkov
            uint64_t x= ff_get_v(bc);
542 e8272029 Michael Niedermayer
            int type= x&1;
543
            int n= j;
544
            x>>=1;
545
            if(type){
546
                int flag= x&1;
547
                x>>=1;
548
                if(n+x >= syncpoint_count + 1){
549
                    av_log(s, AV_LOG_ERROR, "index overflow A\n");
550 c2a3dcaf Michael Niedermayer
                    goto fail;
551 e8272029 Michael Niedermayer
                }
552
                while(x--)
553
                    has_keyframe[n++]= flag;
554
                has_keyframe[n++]= !flag;
555
            }else{
556
                while(x != 1){
557
                    if(n>=syncpoint_count + 1){
558
                        av_log(s, AV_LOG_ERROR, "index overflow B\n");
559 c2a3dcaf Michael Niedermayer
                        goto fail;
560 e8272029 Michael Niedermayer
                    }
561
                    has_keyframe[n++]= x&1;
562
                    x>>=1;
563
                }
564
            }
565
            if(has_keyframe[0]){
566
                av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n");
567 c2a3dcaf Michael Niedermayer
                goto fail;
568 e8272029 Michael Niedermayer
            }
569
            assert(n<=syncpoint_count+1);
570 b19e3983 Oded Shimon
            for(; j<n && j<syncpoint_count; j++){
571 e8272029 Michael Niedermayer
                if(has_keyframe[j]){
572 7798b42d Kostya Shishkov
                    uint64_t B, A= ff_get_v(bc);
573 e8272029 Michael Niedermayer
                    if(!A){
574 7798b42d Kostya Shishkov
                        A= ff_get_v(bc);
575
                        B= ff_get_v(bc);
576 e8272029 Michael Niedermayer
                        //eor_pts[j][i] = last_pts + A + B
577
                    }else
578
                        B= 0;
579
                    av_add_index_entry(
580
                        s->streams[i],
581
                        16*syncpoints[j-1],
582
                        last_pts + A,
583
                        0,
584
                        0,
585
                        AVINDEX_KEYFRAME);
586
                    last_pts += A + B;
587
                }
588
            }
589
        }
590
    }
591
592 5d97d9d5 Michael Niedermayer
    if(skip_reserved(bc, end) || get_checksum(bc)){
593 93951943 Diego Biurrun
        av_log(s, AV_LOG_ERROR, "index checksum mismatch\n");
594 c2a3dcaf Michael Niedermayer
        goto fail;
595 e8272029 Michael Niedermayer
    }
596 c2a3dcaf Michael Niedermayer
    ret= 0;
597
fail:
598
    av_free(syncpoints);
599
    av_free(has_keyframe);
600
    return ret;
601 e8272029 Michael Niedermayer
}
602
603 619d8e2e Michael Niedermayer
static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
604
{
605
    NUTContext *nut = s->priv_data;
606 ae628ec1 Anton Khirnov
    AVIOContext *bc = s->pb;
607 619d8e2e Michael Niedermayer
    int64_t pos;
608 5e534865 Diego Biurrun
    int initialized_stream_count;
609 619d8e2e Michael Niedermayer
610
    nut->avf= s;
611
612
    /* main header */
613
    pos=0;
614 7b0d75fc Michael Niedermayer
    do{
615 619d8e2e Michael Niedermayer
        pos= find_startcode(bc, MAIN_STARTCODE, pos)+1;
616
        if (pos<0+1){
617 93951943 Diego Biurrun
            av_log(s, AV_LOG_ERROR, "No main startcode found.\n");
618 0d3ee135 Stefano Sabatini
            return AVERROR_INVALIDDATA;
619 619d8e2e Michael Niedermayer
        }
620 7b0d75fc Michael Niedermayer
    }while(decode_main_header(nut) < 0);
621 619d8e2e Michael Niedermayer
622
    /* stream headers */
623
    pos=0;
624 5e534865 Diego Biurrun
    for(initialized_stream_count=0; initialized_stream_count < s->nb_streams;){
625 619d8e2e Michael Niedermayer
        pos= find_startcode(bc, STREAM_STARTCODE, pos)+1;
626
        if (pos<0+1){
627 93951943 Diego Biurrun
            av_log(s, AV_LOG_ERROR, "Not all stream headers found.\n");
628 0d3ee135 Stefano Sabatini
            return AVERROR_INVALIDDATA;
629 619d8e2e Michael Niedermayer
        }
630
        if(decode_stream_header(nut) >= 0)
631 5e534865 Diego Biurrun
            initialized_stream_count++;
632 619d8e2e Michael Niedermayer
    }
633
634
    /* info headers */
635
    pos=0;
636
    for(;;){
637
        uint64_t startcode= find_any_startcode(bc, pos);
638
        pos= url_ftell(bc);
639
640
        if(startcode==0){
641
            av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
642 0d3ee135 Stefano Sabatini
            return AVERROR_INVALIDDATA;
643 619d8e2e Michael Niedermayer
        }else if(startcode == SYNCPOINT_STARTCODE){
644
            nut->next_startcode= startcode;
645
            break;
646
        }else if(startcode != INFO_STARTCODE){
647
            continue;
648
        }
649
650
        decode_info_header(nut);
651
    }
652
653 faf7cbf1 Michael Niedermayer
    s->data_offset= pos-8;
654
655 071790c8 Michael Niedermayer
    if(!url_is_streamed(bc)){
656 e8272029 Michael Niedermayer
        int64_t orig_pos= url_ftell(bc);
657
        find_and_decode_index(nut);
658 6b4aa5da Anton Khirnov
        avio_seek(bc, orig_pos, SEEK_SET);
659 e8272029 Michael Niedermayer
    }
660
    assert(nut->next_startcode == SYNCPOINT_STARTCODE);
661
662 03700d39 Anton Khirnov
    ff_metadata_conv_ctx(s, NULL, ff_nut_metadata_conv);
663
664 619d8e2e Michael Niedermayer
    return 0;
665
}
666
667 3b4f69ae Michael Niedermayer
static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, uint8_t *header_idx, int frame_code){
668 619d8e2e Michael Niedermayer
    AVFormatContext *s= nut->avf;
669 ae628ec1 Anton Khirnov
    AVIOContext *bc = s->pb;
670 619d8e2e Michael Niedermayer
    StreamContext *stc;
671
    int size, flags, size_mul, pts_delta, i, reserved_count;
672
    uint64_t tmp;
673
674
    if(url_ftell(bc) > nut->last_syncpoint_pos + nut->max_distance){
675 93951943 Diego Biurrun
        av_log(s, AV_LOG_ERROR, "Last frame must have been damaged %"PRId64" > %"PRId64" + %d\n", url_ftell(bc), nut->last_syncpoint_pos, nut->max_distance);
676 0d3ee135 Stefano Sabatini
        return AVERROR_INVALIDDATA;
677 619d8e2e Michael Niedermayer
    }
678
679
    flags          = nut->frame_code[frame_code].flags;
680
    size_mul       = nut->frame_code[frame_code].size_mul;
681
    size           = nut->frame_code[frame_code].size_lsb;
682
    *stream_id     = nut->frame_code[frame_code].stream_id;
683
    pts_delta      = nut->frame_code[frame_code].pts_delta;
684
    reserved_count = nut->frame_code[frame_code].reserved_count;
685 3b4f69ae Michael Niedermayer
    *header_idx    = nut->frame_code[frame_code].header_idx;
686 619d8e2e Michael Niedermayer
687
    if(flags & FLAG_INVALID)
688 0d3ee135 Stefano Sabatini
        return AVERROR_INVALIDDATA;
689 619d8e2e Michael Niedermayer
    if(flags & FLAG_CODED)
690 7798b42d Kostya Shishkov
        flags ^= ff_get_v(bc);
691 619d8e2e Michael Niedermayer
    if(flags & FLAG_STREAM_ID){
692
        GET_V(*stream_id, tmp < s->nb_streams)
693
    }
694
    stc= &nut->stream[*stream_id];
695
    if(flags&FLAG_CODED_PTS){
696 7798b42d Kostya Shishkov
        int coded_pts= ff_get_v(bc);
697 619d8e2e Michael Niedermayer
//FIXME check last_pts validity?
698
        if(coded_pts < (1<<stc->msb_pts_shift)){
699 f13ea4e0 Michael Niedermayer
            *pts=ff_lsb2full(stc, coded_pts);
700 619d8e2e Michael Niedermayer
        }else
701
            *pts=coded_pts - (1<<stc->msb_pts_shift);
702
    }else
703
        *pts= stc->last_pts + pts_delta;
704
    if(flags&FLAG_SIZE_MSB){
705 7798b42d Kostya Shishkov
        size += size_mul*ff_get_v(bc);
706 619d8e2e Michael Niedermayer
    }
707 7eeebcc5 Michael Niedermayer
    if(flags&FLAG_MATCH_TIME)
708
        get_s(bc);
709 3b4f69ae Michael Niedermayer
    if(flags&FLAG_HEADER_IDX)
710
        *header_idx= ff_get_v(bc);
711 619d8e2e Michael Niedermayer
    if(flags&FLAG_RESERVED)
712 7798b42d Kostya Shishkov
        reserved_count= ff_get_v(bc);
713 619d8e2e Michael Niedermayer
    for(i=0; i<reserved_count; i++)
714 7798b42d Kostya Shishkov
        ff_get_v(bc);
715 3b4f69ae Michael Niedermayer
716
    if(*header_idx >= (unsigned)nut->header_count){
717
        av_log(s, AV_LOG_ERROR, "header_idx invalid\n");
718 0d3ee135 Stefano Sabatini
        return AVERROR_INVALIDDATA;
719 3b4f69ae Michael Niedermayer
    }
720
    if(size > 4096)
721
        *header_idx=0;
722
    size -= nut->header_len[*header_idx];
723
724 619d8e2e Michael Niedermayer
    if(flags&FLAG_CHECKSUM){
725 b7effd4e Anton Khirnov
        avio_rb32(bc); //FIXME check this
726 06599638 Michael Niedermayer
    }else if(size > 2*nut->max_distance || FFABS(stc->last_pts - *pts) > stc->max_pts_distance){
727 2dbe0bd4 Michael Niedermayer
        av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n");
728 0d3ee135 Stefano Sabatini
        return AVERROR_INVALIDDATA;
729 619d8e2e Michael Niedermayer
    }
730
731
    stc->last_pts= *pts;
732 06599638 Michael Niedermayer
    stc->last_flags= flags;
733 619d8e2e Michael Niedermayer
734
    return size;
735
}
736
737
static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code){
738
    AVFormatContext *s= nut->avf;
739 ae628ec1 Anton Khirnov
    AVIOContext *bc = s->pb;
740 06599638 Michael Niedermayer
    int size, stream_id, discard;
741 619d8e2e Michael Niedermayer
    int64_t pts, last_IP_pts;
742 06599638 Michael Niedermayer
    StreamContext *stc;
743 3b4f69ae Michael Niedermayer
    uint8_t header_idx;
744 619d8e2e Michael Niedermayer
745 3b4f69ae Michael Niedermayer
    size= decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code);
746 619d8e2e Michael Niedermayer
    if(size < 0)
747 0d3ee135 Stefano Sabatini
        return size;
748 619d8e2e Michael Niedermayer
749 06599638 Michael Niedermayer
    stc= &nut->stream[stream_id];
750
751
    if (stc->last_flags & FLAG_KEY)
752
        stc->skip_until_key_frame=0;
753 0a3b575b Michael Niedermayer
754 619d8e2e Michael Niedermayer
    discard= s->streams[ stream_id ]->discard;
755
    last_IP_pts= s->streams[ stream_id ]->last_IP_pts;
756 06599638 Michael Niedermayer
    if(  (discard >= AVDISCARD_NONKEY && !(stc->last_flags & FLAG_KEY))
757 619d8e2e Michael Niedermayer
       ||(discard >= AVDISCARD_BIDIR && last_IP_pts != AV_NOPTS_VALUE && last_IP_pts > pts)
758 0a3b575b Michael Niedermayer
       || discard >= AVDISCARD_ALL
759 06599638 Michael Niedermayer
       || stc->skip_until_key_frame){
760 e356fc57 Anton Khirnov
        avio_seek(bc, size, SEEK_CUR);
761 619d8e2e Michael Niedermayer
        return 1;
762
    }
763
764 3b4f69ae Michael Niedermayer
    av_new_packet(pkt, size + nut->header_len[header_idx]);
765
    memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]);
766
    pkt->pos= url_ftell(bc); //FIXME
767 b7effd4e Anton Khirnov
    avio_read(bc, pkt->data + nut->header_len[header_idx], size);
768 3b4f69ae Michael Niedermayer
769 619d8e2e Michael Niedermayer
    pkt->stream_index = stream_id;
770 06599638 Michael Niedermayer
    if (stc->last_flags & FLAG_KEY)
771 cc947f04 Jean-Daniel Dupas
        pkt->flags |= AV_PKT_FLAG_KEY;
772 619d8e2e Michael Niedermayer
    pkt->pts = pts;
773
774
    return 0;
775
}
776
777
static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
778
{
779
    NUTContext *nut = s->priv_data;
780 ae628ec1 Anton Khirnov
    AVIOContext *bc = s->pb;
781 619d8e2e Michael Niedermayer
    int i, frame_code=0, ret, skip;
782 4d5be986 Michael Niedermayer
    int64_t ts, back_ptr;
783 619d8e2e Michael Niedermayer
784
    for(;;){
785
        int64_t pos= url_ftell(bc);
786
        uint64_t tmp= nut->next_startcode;
787
        nut->next_startcode=0;
788
789
        if(tmp){
790
            pos-=8;
791
        }else{
792 b7effd4e Anton Khirnov
            frame_code = avio_r8(bc);
793 559fd1e7 Clemens Ladisch
            if(url_feof(bc))
794
                return -1;
795 619d8e2e Michael Niedermayer
            if(frame_code == 'N'){
796
                tmp= frame_code;
797
                for(i=1; i<8; i++)
798 b7effd4e Anton Khirnov
                    tmp = (tmp<<8) + avio_r8(bc);
799 619d8e2e Michael Niedermayer
            }
800
        }
801
        switch(tmp){
802
        case MAIN_STARTCODE:
803
        case STREAM_STARTCODE:
804
        case INDEX_STARTCODE:
805 073811cd Michael Niedermayer
            skip= get_packetheader(nut, bc, 0, tmp);
806 6b4aa5da Anton Khirnov
            avio_seek(bc, skip, SEEK_CUR);
807 619d8e2e Michael Niedermayer
            break;
808
        case INFO_STARTCODE:
809
            if(decode_info_header(nut)<0)
810
                goto resync;
811
            break;
812
        case SYNCPOINT_STARTCODE:
813 4d5be986 Michael Niedermayer
            if(decode_syncpoint(nut, &ts, &back_ptr)<0)
814 619d8e2e Michael Niedermayer
                goto resync;
815 b7effd4e Anton Khirnov
            frame_code = avio_r8(bc);
816 619d8e2e Michael Niedermayer
        case 0:
817
            ret= decode_frame(nut, pkt, frame_code);
818
            if(ret==0)
819
                return 0;
820
            else if(ret==1) //ok but discard packet
821
                break;
822
        default:
823
resync:
824
av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", pos);
825 8ba3e5d8 Michael Niedermayer
            tmp= find_any_startcode(bc, nut->last_syncpoint_pos+1);
826 619d8e2e Michael Niedermayer
            if(tmp==0)
827 0d3ee135 Stefano Sabatini
                return AVERROR_INVALIDDATA;
828 619d8e2e Michael Niedermayer
av_log(s, AV_LOG_DEBUG, "sync\n");
829
            nut->next_startcode= tmp;
830
        }
831
    }
832
}
833
834 faf7cbf1 Michael Niedermayer
static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit){
835
    NUTContext *nut = s->priv_data;
836 ae628ec1 Anton Khirnov
    AVIOContext *bc = s->pb;
837 4d5be986 Michael Niedermayer
    int64_t pos, pts, back_ptr;
838 faf7cbf1 Michael Niedermayer
av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n", stream_index, *pos_arg, pos_limit);
839
840
    pos= *pos_arg;
841
    do{
842
        pos= find_startcode(bc, SYNCPOINT_STARTCODE, pos)+1;
843
        if(pos < 1){
844
            assert(nut->next_startcode == 0);
845 93951943 Diego Biurrun
            av_log(s, AV_LOG_ERROR, "read_timestamp failed.\n");
846 faf7cbf1 Michael Niedermayer
            return AV_NOPTS_VALUE;
847
        }
848 4d5be986 Michael Niedermayer
    }while(decode_syncpoint(nut, &pts, &back_ptr) < 0);
849 faf7cbf1 Michael Niedermayer
    *pos_arg = pos-1;
850
    assert(nut->last_syncpoint_pos == *pos_arg);
851
852 706da4af Måns Rullgård
    av_log(s, AV_LOG_DEBUG, "return %"PRId64" %"PRId64"\n", pts,back_ptr );
853 4d5be986 Michael Niedermayer
    if     (stream_index == -1) return pts;
854
    else if(stream_index == -2) return back_ptr;
855
856
assert(0);
857 faf7cbf1 Michael Niedermayer
}
858
859 4d5be986 Michael Niedermayer
static int read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags){
860
    NUTContext *nut = s->priv_data;
861
    AVStream *st= s->streams[stream_index];
862 52afa376 Michael Niedermayer
    Syncpoint dummy={.ts= pts*av_q2d(st->time_base)*AV_TIME_BASE};
863
    Syncpoint nopts_sp= {.ts= AV_NOPTS_VALUE, .back_ptr= AV_NOPTS_VALUE};
864
    Syncpoint *sp, *next_node[2]= {&nopts_sp, &nopts_sp};
865 4d5be986 Michael Niedermayer
    int64_t pos, pos2, ts;
866 0a3b575b Michael Niedermayer
    int i;
867 4d5be986 Michael Niedermayer
868 071790c8 Michael Niedermayer
    if(st->index_entries){
869
        int index= av_index_search_timestamp(st, pts, flags);
870
        if(index<0)
871
            return -1;
872
873
        pos2= st->index_entries[index].pos;
874
        ts  = st->index_entries[index].timestamp;
875
    }else{
876 f990f6e3 Vitor Sessak
        av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pts_cmp,
877
                     (void **) next_node);
878 706da4af Måns Rullgård
        av_log(s, AV_LOG_DEBUG, "%"PRIu64"-%"PRIu64" %"PRId64"-%"PRId64"\n", next_node[0]->pos, next_node[1]->pos,
879 f32554fa Michael Niedermayer
                                                    next_node[0]->ts , next_node[1]->ts);
880
        pos= av_gen_search(s, -1, dummy.ts, next_node[0]->pos, next_node[1]->pos, next_node[1]->pos,
881
                                            next_node[0]->ts , next_node[1]->ts, AVSEEK_FLAG_BACKWARD, &ts, nut_read_timestamp);
882
883
        if(!(flags & AVSEEK_FLAG_BACKWARD)){
884
            dummy.pos= pos+16;
885
            next_node[1]= &nopts_sp;
886 f990f6e3 Vitor Sessak
            av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
887
                         (void **) next_node);
888 f32554fa Michael Niedermayer
            pos2= av_gen_search(s, -2, dummy.pos, next_node[0]->pos     , next_node[1]->pos, next_node[1]->pos,
889
                                                next_node[0]->back_ptr, next_node[1]->back_ptr, flags, &ts, nut_read_timestamp);
890
            if(pos2>=0)
891
                pos= pos2;
892 2cab6401 Diego Biurrun
            //FIXME dir but I think it does not matter
893 f32554fa Michael Niedermayer
        }
894
        dummy.pos= pos;
895 f990f6e3 Vitor Sessak
        sp= av_tree_find(nut->syncpoints, &dummy, (void *) ff_nut_sp_pos_cmp,
896
                         NULL);
897 f32554fa Michael Niedermayer
898
        assert(sp);
899
        pos2= sp->back_ptr  - 15;
900 071790c8 Michael Niedermayer
    }
901
    av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2);
902 899681cd Björn Axelsson
    pos= find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2);
903 6b4aa5da Anton Khirnov
    avio_seek(s->pb, pos, SEEK_SET);
904 4d5be986 Michael Niedermayer
    av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos);
905 071790c8 Michael Niedermayer
    if(pos2 > pos || pos2 + 15 < pos){
906 4d5be986 Michael Niedermayer
        av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n");
907
    }
908 0a3b575b Michael Niedermayer
    for(i=0; i<s->nb_streams; i++)
909
        nut->stream[i].skip_until_key_frame=1;
910
911 4d5be986 Michael Niedermayer
    return 0;
912
}
913
914 619d8e2e Michael Niedermayer
static int nut_read_close(AVFormatContext *s)
915
{
916
    NUTContext *nut = s->priv_data;
917 27dbc47c Vitor Sessak
    int i;
918 619d8e2e Michael Niedermayer
919
    av_freep(&nut->time_base);
920
    av_freep(&nut->stream);
921 4b83fc0f Vitor Sessak
    ff_nut_free_sp(nut);
922 27dbc47c Vitor Sessak
    for(i = 1; i < nut->header_count; i++)
923
        av_freep(&nut->header[i]);
924 619d8e2e Michael Niedermayer
925
    return 0;
926
}
927
928 b250f9c6 Aurelien Jacobs
#if CONFIG_NUT_DEMUXER
929 c6610a21 Diego Elio Pettenò
AVInputFormat ff_nut_demuxer = {
930 619d8e2e Michael Niedermayer
    "nut",
931 bde15e74 Stefano Sabatini
    NULL_IF_CONFIG_SMALL("NUT format"),
932 619d8e2e Michael Niedermayer
    sizeof(NUTContext),
933
    nut_probe,
934
    nut_read_header,
935
    nut_read_packet,
936
    nut_read_close,
937 4d5be986 Michael Niedermayer
    read_seek,
938 619d8e2e Michael Niedermayer
    .extensions = "nut",
939 2e01def0 Stefano Sabatini
    .codec_tag = (const AVCodecTag * const []) { ff_codec_bmp_tags, ff_nut_video_tags, ff_codec_wav_tags, ff_nut_subtitle_tags, 0 },
940 619d8e2e Michael Niedermayer
};
941
#endif