Statistics
| Branch: | Revision:

ffmpeg / libavformat / nutdec.c @ 3abe5fbd

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