Statistics
| Branch: | Revision:

ffmpeg / libavformat / nutdec.c @ 47772399

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