Statistics
| Branch: | Revision:

ffmpeg / libavformat / nutdec.c @ 663a5d9d

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