Statistics
| Branch: | Revision:

ffmpeg / libavformat / nutdec.c @ d7fb5a18

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