Statistics
| Branch: | Revision:

ffmpeg / libavformat / nutdec.c @ 53620bba

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