Statistics
| Branch: | Revision:

ffmpeg / libavformat / nutdec.c @ acaceca2

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