Revision 0b43db14 libavformat/nut.c

View differences:

libavformat/nut.c
47 47
#define    INDEX_STARTCODE (0xDD672F23E64EULL + (((uint64_t)('N'<<8) + 'X')<<48)) 
48 48
#define     INFO_STARTCODE (0xAB68B596BA78ULL + (((uint64_t)('N'<<8) + 'I')<<48)) 
49 49

  
50
#define MAX_TYPE1_DISTANCE (1024*16-1)
51
#define MAX_TYPE2_DISTANCE (1024*64-1)
50
#define MAX_DISTANCE (1024*16-1)
51
#define MAX_SHORT_DISTANCE (1024*4-1)
52 52

  
53
#define MAX_SIZE_LRU 2
54 53
#define MAX_PTS_LRU 3
55 54

  
56
#define FLAG_FRAME_TYPE      1
57
#define FLAG_DATA_SIZE       2
58
#define FLAG_PTS            16
59
#define FLAG_FULL_PTS        4
60
#define FLAG_KEY_FRAME      32
55
#define FLAG_DATA_SIZE       4
56
#define FLAG_PTS             3
57
#define FLAG_KEY_FRAME       8
61 58

  
62 59
typedef struct {
63 60
    uint8_t flags;
64 61
    uint8_t stream_id_plus1;
65
    uint8_t size_mul;
66
    uint8_t size_lsb;
62
    uint16_t size_mul;
63
    uint16_t size_lsb;
67 64
} FrameCode;
68 65

  
69 66
typedef struct {
......
72 69
    int rate_num;
73 70
    int rate_den;
74 71
    int64_t last_pts;
75
    int64_t last_full_pts;
76 72
    int lru_pts_delta[MAX_PTS_LRU];
77
    int lru_size[MAX_SIZE_LRU];
78 73
    int initial_pts_predictor[MAX_PTS_LRU];
79
    int initial_size_predictor[MAX_SIZE_LRU];
80 74
    int64_t last_sync_pos;                    ///<pos of last 1/2 type frame
75
    int decode_delay;
81 76
} StreamContext;
82 77

  
83 78
typedef struct {
84 79
    AVFormatContext *avf;
85
    int64_t packet_start;
86
    int64_t last_packet_start;
87 80
    int written_packet_size;
88
    int64_t packet_size_pos;
89
    int64_t last_frame_start[3];
81
    int64_t packet_start[3]; //0-> startcode less, 1-> short startcode 2-> long startcodes
90 82
    FrameCode frame_code[256];
91 83
    int stream_count;
92 84
    uint64_t next_startcode;     ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable
93 85
    StreamContext *stream;
86
    int max_distance;
94 87
} NUTContext;
95 88

  
96 89
static char *info_table[][2]={
......
130 123

  
131 124
static void update(NUTContext *nut, int stream_index, int64_t frame_start, int frame_type, int frame_code, int key_frame, int size, int64_t pts){
132 125
    StreamContext *stream= &nut->stream[stream_index];
133
    const int flags=nut->frame_code[frame_code].flags; 
134 126
    
135 127
    stream->last_key_frame= key_frame;
136
    nut->last_frame_start[ frame_type ]= frame_start;
137
    if(frame_type == 0)
128
    nut->packet_start[ frame_type ]= frame_start;
129
    if(stream->last_pts != AV_NOPTS_VALUE){
130
        assert(frame_type < 2);
138 131
        update_lru(stream->lru_pts_delta, pts - stream->last_pts, 3);
139
    update_lru(stream->lru_size, size, 2);
132
    }
140 133
    stream->last_pts= pts;
141
    if((flags & FLAG_PTS) && (flags & FLAG_FULL_PTS))
142
        stream->last_full_pts= pts;
143 134
}
144 135

  
145 136
static void reset(AVFormatContext *s/*, int frame_type*/){
......
150 141
        StreamContext *stream= &nut->stream[i];
151 142
    
152 143
        stream->last_key_frame= 1;
144
        stream->last_pts= AV_NOPTS_VALUE;
153 145
        memcpy(stream->lru_pts_delta, stream->initial_pts_predictor, sizeof(int)*MAX_PTS_LRU);
154
        memcpy(stream->lru_size, stream->initial_size_predictor, sizeof(int)*MAX_SIZE_LRU);
155 146
    }
156 147
}
157 148

  
158 149
static void build_frame_code(AVFormatContext *s){
159 150
    NUTContext *nut = s->priv_data;
160
    int key_frame, frame_type, full_pts, index, pred, stream_id;
151
    int key_frame, index, pred, stream_id, full_pts;
161 152
    int start=0;
162 153
    int end= 255;
163 154
    int keyframe_0_esc= s->nb_streams > 2;
164 155

  
165 156
    if(keyframe_0_esc){
166
        /* keyframe = 0 escapes, 3 codes */
167
        for(frame_type=0; frame_type<2; frame_type++){
168
            for(full_pts=frame_type; full_pts<2; full_pts++){
169
                FrameCode *ft= &nut->frame_code[start];
170
                ft->flags= FLAG_FRAME_TYPE*frame_type + FLAG_FULL_PTS*full_pts;
171
                ft->flags|= FLAG_DATA_SIZE | FLAG_PTS; 
172
                ft->stream_id_plus1= 0;
173
                ft->size_mul=1;
174
                start++;
175
            }
176
        }
157
        /* keyframe = 0 escape */
158
        FrameCode *ft= &nut->frame_code[start];
159
        ft->flags= FLAG_DATA_SIZE | FLAG_PTS; 
160
        ft->stream_id_plus1= 0;
161
        ft->size_mul=1;
162
        start++;
177 163
    }
178 164

  
179 165
    for(stream_id= 0; stream_id<s->nb_streams; stream_id++){
......
188 174
            if(intra_only && keyframe_0_esc && key_frame==0)
189 175
                continue;
190 176
            
191
            for(frame_type=0; frame_type<2; frame_type++){
192
                for(full_pts=frame_type; full_pts<2; full_pts++){
193
                    FrameCode *ft= &nut->frame_code[start2];
194
                    ft->flags= FLAG_FRAME_TYPE*frame_type + FLAG_FULL_PTS*full_pts + FLAG_KEY_FRAME*key_frame;
195
                    ft->flags|= FLAG_DATA_SIZE | FLAG_PTS;
196
                    ft->stream_id_plus1= stream_id + 1;
197
                    ft->size_mul=1;
198
                    start2++;
199
                }
177
            {
178
                FrameCode *ft= &nut->frame_code[start2];
179
                ft->flags= FLAG_KEY_FRAME*key_frame;
180
                ft->flags|= FLAG_DATA_SIZE | FLAG_PTS;
181
                ft->stream_id_plus1= stream_id + 1;
182
                ft->size_mul=1;
183
                start2++;
200 184
            }
201 185
        }
202 186

  
......
204 188
#if 1
205 189
        if(is_audio){
206 190
            int frame_bytes= codec->frame_size*(int64_t)codec->bit_rate / (8*codec->sample_rate);
207
            for(pred=0; pred<MAX_SIZE_LRU; pred++){
208
                for(frame_type=0; frame_type<1; frame_type++){
191
            for(full_pts=0; full_pts<2; full_pts++){
192
                for(pred=0; pred<2; pred++){
209 193
                    FrameCode *ft= &nut->frame_code[start2];
210
                    ft->flags= FLAG_KEY_FRAME*key_frame + (FLAG_FULL_PTS+FLAG_PTS+FLAG_FRAME_TYPE)*frame_type;
194
                    ft->flags= FLAG_KEY_FRAME*key_frame + FLAG_PTS*full_pts;
211 195
                    ft->stream_id_plus1= stream_id + 1;
212
                    ft->size_mul=1;
213
                    ft->size_lsb=1 + pred;
196
                    ft->size_mul=frame_bytes + 2;
197
                    ft->size_lsb=frame_bytes + pred;
214 198
                    start2++;
199
                    av_log(NULL, AV_LOG_DEBUG, "%d\n", frame_bytes + pred);
215 200
                }
216
                nut->stream[stream_id].initial_size_predictor[pred]= frame_bytes + pred;
217 201
            }
218 202
        }else{
219 203
            FrameCode *ft= &nut->frame_code[start2];
......
254 238

  
255 239
	if (tmp&0x80)
256 240
	    val= (val<<7) + tmp - 0x80;
257
	else
241
	else{
242
//av_log(NULL, AV_LOG_DEBUG, "get_v()= %lld\n", (val<<7) + tmp);
258 243
	    return (val<<7) + tmp;
244
        }
259 245
    }
260 246
    return -1;
261 247
}
......
289 275
    while(i--)
290 276
        val = (val<<8) + get_byte(bc);
291 277
    
278
//av_log(NULL, AV_LOG_DEBUG, "get_vb()= %lld\n", val);
292 279
    return val;
293 280
}
294 281

  
295
static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_length, int calculate_checksum)
282
static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int calculate_checksum)
296 283
{
297
    int64_t start, size, last_size;
298
    start= url_ftell(bc) - prefix_length;
284
    int64_t start, size;
285
    start= url_ftell(bc) - 8;
299 286

  
300
    if(nut->written_packet_size >= 0 && start != nut->packet_start + nut->written_packet_size){
301
        av_log(nut->avf, AV_LOG_ERROR, "get_packetheader called at weird position\n");
302
        if(prefix_length<8)
303
            return -1;
304
    }
305
    
306 287
    init_checksum(bc, calculate_checksum ? update_adler32 : NULL, 0);
307 288

  
308 289
    size= get_v(bc);
309
    last_size= get_v(bc);
310
    if(nut->written_packet_size >= 0 && nut->written_packet_size != last_size){
311
        av_log(nut->avf, AV_LOG_ERROR, "packet size missmatch %d != %lld at %lld\n", nut->written_packet_size, last_size, start);
312
        if(prefix_length<8)
313
            return -1;
314
    }
315 290

  
316
    nut->last_packet_start = nut->packet_start;
317
    nut->packet_start = start;
291
    nut->packet_start[2] = start;
318 292
    nut->written_packet_size= size;
319 293

  
320 294
    return size;
......
381 355
{
382 356
    int i;
383 357

  
358
//av_log(NULL, AV_LOG_DEBUG, "put_v()= %lld\n", val);
384 359
    val &= 0x7FFFFFFFFFFFFFFFULL; // FIXME can only encode upto 63 bits currently
385 360
    i= get_length(val);
386 361

  
......
414 389
static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size, int calculate_checksum)
415 390
{
416 391
    put_flush_packet(bc);
417
    nut->last_packet_start= nut->packet_start;
418
    nut->packet_start+= nut->written_packet_size;
419
    nut->packet_size_pos = url_ftell(bc);
392
    nut->packet_start[2]+= nut->written_packet_size;
393
    assert(url_ftell(bc) - 8 == nut->packet_start[2]);
420 394
    nut->written_packet_size = max_size;
421 395
    
422 396
    if(calculate_checksum)
......
424 398

  
425 399
    /* packet header */
426 400
    put_v(bc, nut->written_packet_size); /* forward ptr */
427
    put_v(bc, nut->packet_start - nut->last_packet_start); /* backward ptr */
428 401

  
429 402
    return 0;
430 403
}
431 404

  
432 405
static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size, int calculate_checksum){
433
    int64_t start= nut->packet_start;
406
    int64_t start= nut->packet_start[2];
434 407
    int64_t cur= url_ftell(bc);
435 408
    int size= cur - start + additional_size;
436 409
    
......
442 415

  
443 416
        assert( size <= nut->written_packet_size );
444 417
    
445
        url_fseek(bc, nut->packet_size_pos, SEEK_SET);
418
        url_fseek(bc, start + 8, SEEK_SET);
446 419
        for(i=get_length(size); i < get_length(nut->written_packet_size); i+=7)
447 420
            put_byte(bc, 0x80);
448 421
        put_v(bc, size);
......
474 447
    /* main header */
475 448
    put_be64(bc, MAIN_STARTCODE);
476 449
    put_packetheader(nut, bc, 120+5*256, 1);
477
    put_v(bc, 1); /* version */
450
    put_v(bc, 2); /* version */
478 451
    put_v(bc, s->nb_streams);
452
    put_v(bc, MAX_DISTANCE);
479 453
    
480 454
    build_frame_code(s);
481 455
    assert(nut->frame_code['N'].flags == 1);
......
558 532
	put_v(bc, nut->stream[i].msb_timestamp_shift);
559 533
	for(j=0; j<3; j++)
560 534
		put_v(bc, nut->stream[i].initial_pts_predictor[j]);
561
	for(j=0; j<2; j++)
562
		put_v(bc, nut->stream[i].initial_size_predictor[j]);
535
        put_v(bc, codec->has_b_frames);
563 536
	put_byte(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
564 537
	
565 538
        if(codec->extradata_size){
......
572 545
	switch(codec->codec_type)
573 546
	{
574 547
	    case CODEC_TYPE_AUDIO:
575
		put_v(bc, (codec->sample_rate * denom) / nom);
548
		put_v(bc, codec->sample_rate);
549
		put_v(bc, 1);
576 550
		put_v(bc, codec->channels);
577 551
		break;
578 552
	    case CODEC_TYPE_VIDEO:
......
626 600
    return 0;
627 601
}
628 602

  
603
static int64_t lsb2full(StreamContext *stream, int64_t lsb){
604
    int64_t mask = (1<<stream->msb_timestamp_shift)-1;
605
    int64_t delta= stream->last_pts - mask/2;
606
    return  ((lsb - delta)&mask) + delta;
607
}
608

  
629 609
static int nut_write_packet(AVFormatContext *s, int stream_index, 
630 610
			    const uint8_t *buf, int size, int64_t pts)
631 611
{
......
634 614
    ByteIOContext *bc = &s->pb;
635 615
    int key_frame = 0, full_pts=0;
636 616
    AVCodecContext *enc;
637
    int64_t lsb_pts, delta_pts;
617
    int64_t coded_pts;
638 618
    int frame_type, best_length, frame_code, flags, i, size_mul, size_lsb;
639 619
    const int64_t frame_start= url_ftell(bc);
640 620

  
......
647 627
    key_frame = enc->coded_frame->key_frame;
648 628
    if(enc->coded_frame->pts != AV_NOPTS_VALUE)
649 629
        pts= (av_rescale(enc->coded_frame->pts, stream->rate_num, stream->rate_den) + AV_TIME_BASE/2) / AV_TIME_BASE; //FIXME XXX HACK
650
    delta_pts= pts - stream->last_pts;
651 630
    
652 631
    frame_type=0;
653
    if(frame_start + size + 20 - FFMAX(nut->last_frame_start[1], nut->last_frame_start[2]) > MAX_TYPE1_DISTANCE)
654
        frame_type=1;
655
    if(key_frame){
656
        if(frame_type==1 && frame_start + size - nut->last_frame_start[2] > MAX_TYPE2_DISTANCE)
657
            frame_type=2;
658
        if(!stream->last_key_frame)
659
            frame_type=2;
660
    }
632
    if(frame_start + size + 20 - FFMAX(nut->packet_start[1], nut->packet_start[2]) > MAX_DISTANCE)
633
        frame_type=2;
634
    if(key_frame && !stream->last_key_frame)
635
        frame_type=2;
661 636

  
662
    if(frame_type>0){
663
        update_packetheader(nut, bc, 0, 0);
637
    if(frame_type>1)
664 638
        reset(s);
639
    if(stream->last_pts == AV_NOPTS_VALUE)
665 640
        full_pts=1;
641
    else{
642
        coded_pts = pts & ((1<<stream->msb_timestamp_shift)-1);
643
        if(lsb2full(stream, coded_pts) != pts)
644
            full_pts=1;
666 645
    }
667
    //FIXME ensure that the timestamp can be represented by either delta or lsb or full_pts=1
668 646

  
669
    lsb_pts = pts & ((1 << stream->msb_timestamp_shift)-1);
647
    if(full_pts)
648
        coded_pts= pts + (1<<stream->msb_timestamp_shift);
670 649

  
671 650
    best_length=INT_MAX;
672 651
    frame_code= -1;
......
678 657
        size_lsb= nut->frame_code[i].size_lsb;
679 658
        flags= nut->frame_code[i].flags;
680 659

  
660
        assert(size_mul > size_lsb);
661
        
681 662
        if(stream_id_plus1 == 0) length+= get_length(stream_index);
682 663
        else if(stream_id_plus1 - 1 != stream_index)
683 664
            continue;
......
687 668
        if(fc_key_frame != key_frame)
688 669
            continue;
689 670

  
690
        if((!!(flags & FLAG_FRAME_TYPE)) != (frame_type > 0))
691
            continue;
692
        
693
        if(size_mul <= size_lsb){
694
            int p= stream->lru_size[size_lsb - size_mul];
695
            if(p != size)
696
                continue;
697
        }else{
671
        if(flags & FLAG_DATA_SIZE){
698 672
            if(size % size_mul != size_lsb)
699 673
                continue;
700
            if(flags & FLAG_DATA_SIZE)
701
                length += get_length(size / size_mul);
702
            else if(size/size_mul)
703
                continue;
704
        }
674
            length += get_length(size / size_mul);
675
        }else if(size != size_lsb)
676
            continue;
705 677

  
706
        if(full_pts != ((flags & FLAG_PTS) && (flags & FLAG_FULL_PTS)))
678
        if(full_pts && (flags & FLAG_PTS) != FLAG_PTS)
707 679
            continue;
708 680
            
709 681
        if(flags&FLAG_PTS){
710
            if(flags&FLAG_FULL_PTS){
711
                length += get_length(pts);
712
            }else{
713
                length += get_length(lsb_pts);
714
            }
682
            length += get_length(coded_pts);
715 683
        }else{
716
            int delta= stream->lru_pts_delta[(flags & 12)>>2];
684
            int delta= stream->lru_pts_delta[flags & FLAG_PTS];
717 685
            if(delta != pts - stream->last_pts)
718 686
                continue;
719
            assert(frame_type == 0);
687
            assert(frame_type < 2);
720 688
        }
721 689

  
722 690
        if(length < best_length){
......
733 701
#if 0
734 702
    best_length /= 7;
735 703
    best_length ++; //frame_code
736
    if(frame_type>0){
737
        best_length += 4; //packet header
738
        if(frame_type>1)
739
            best_length += 8; // startcode
704
    if(frame_type==2){
705
        best_length += 8; // startcode
740 706
    }
741
    av_log(s, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d size:%d stream:%d flag:%d mul:%d lsb:%d s+1:%d pts_delta:%d\n", key_frame, frame_type, full_pts ? 2 : ((flags & FLAG_PTS) ? 1 : 0), frame_code, best_length, size, stream_index, flags, size_mul, size_lsb, nut->frame_code[frame_code].stream_id_plus1,(int)(pts - stream->last_pts));
707
    av_log(s, AV_LOG_DEBUG, "kf:%d ft:%d pt:%d fc:%2X len:%2d size:%d stream:%d flag:%d mul:%d lsb:%d s+1:%d pts_delta:%d pts:%lld\n", key_frame, frame_type, full_pts ? 2 : ((flags & FLAG_PTS) == FLAG_PTS ? 1 : 0), frame_code, best_length, size, stream_index, flags, size_mul, size_lsb, nut->frame_code[frame_code].stream_id_plus1,(int)(pts - stream->last_pts), pts);
708
//    av_log(s, AV_LOG_DEBUG, "%d %d %d\n", stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);
742 709
#endif
743 710

  
744 711
    if (frame_type==2)
745 712
	put_be64(bc, KEYFRAME_STARTCODE);
713
    assert(frame_type != 1); //short startcode not implemented yet
746 714
    put_byte(bc, frame_code);
747 715

  
748
    if(frame_type>0)
749
        put_packetheader(nut, bc, FFMAX(size+20, MAX_TYPE1_DISTANCE), 0);
750 716
    if(nut->frame_code[frame_code].stream_id_plus1 == 0)
751 717
        put_v(bc, stream_index);
752
    if (flags & FLAG_PTS){
753
        if (flags & FLAG_FULL_PTS)
754
            put_v(bc, pts);
755
        else
756
            put_v(bc, lsb_pts);
718
    if ((flags & FLAG_PTS) == FLAG_PTS){
719
        put_v(bc, coded_pts);
757 720
    }
758 721
    if(flags & FLAG_DATA_SIZE)
759 722
        put_v(bc, size / size_mul);
760
    if(size > MAX_TYPE1_DISTANCE){
761
        assert(frame_type > 0);
762
        update_packetheader(nut, bc, size, 0);
723
    if(size > MAX_DISTANCE){
724
        assert(frame_type > 1);
763 725
    }
764 726
    
765 727
    put_buffer(bc, buf, size);
......
774 736
    NUTContext *nut = s->priv_data;
775 737
    ByteIOContext *bc = &s->pb;
776 738

  
777
    update_packetheader(nut, bc, 0, 0);
778

  
779 739
#if 0
780 740
    int i;
781 741

  
......
802 762
static int nut_probe(AVProbeData *p)
803 763
{
804 764
    int i;
805
    uint64_t code;
765
    uint64_t code= 0xff;
806 766

  
807
    code = 0xff;
808 767
    for (i = 0; i < p->buf_size; i++) {
809
        int c = p->buf[i];
810
        code = (code << 8) | c;
768
        code = (code << 8) | p->buf[i];
811 769
        if (code == MAIN_STARTCODE)
812 770
            return AVPROBE_SCORE_MAX;
813 771
    }
......
820 778
    uint64_t tmp;
821 779
    int i, j;
822 780
    
823
    get_packetheader(nut, bc, 8, 1);
781
    get_packetheader(nut, bc, 1);
824 782

  
825 783
    tmp = get_v(bc);
826
    if (tmp != 1){
784
    if (tmp != 2){
827 785
	av_log(s, AV_LOG_ERROR, "bad version (%Ld)\n", tmp);
828 786
        return -1;
829 787
    }
830 788
    
831 789
    nut->stream_count = get_v(bc);
832

  
790
    nut->max_distance = get_v(bc);
791
    
833 792
    for(i=0; i<256;){
834 793
        int tmp_flags = get_v(bc);
835 794
        int tmp_stream= get_v(bc);
......
842 801
            return -1;
843 802
        }
844 803

  
845
        if((tmp_flags & FLAG_FRAME_TYPE) && tmp_flags != 1){
846
            if(!(tmp_flags & FLAG_PTS) || !(tmp_flags & FLAG_FULL_PTS) ){
847
                av_log(s, AV_LOG_ERROR, "no full pts in non 0 frame type\n");
848
                return -1;
849
            }
850
        }
851

  
852 804
        for(j=0; j<count; j++,i++){
853 805
            if(tmp_stream > nut->stream_count + 1){
854 806
                av_log(s, AV_LOG_ERROR, "illegal stream number\n");
......
885 837
    uint64_t tmp;
886 838
    AVStream *st;
887 839
    
888
    get_packetheader(nut, bc, 8, 1);
840
    get_packetheader(nut, bc, 1);
889 841
    stream_id= get_v(bc);
890 842
    if(stream_id >= nut->stream_count || s->streams[stream_id])
891 843
        return -1;
......
920 872
    denom = get_v(bc);
921 873
    nut->stream[stream_id].msb_timestamp_shift = get_v(bc);
922 874
    for(i=0; i<3; i++)
923
            nut->stream[stream_id].initial_pts_predictor[i]= get_v(bc);
924
    for(i=0; i<2; i++)
925
            nut->stream[stream_id].initial_size_predictor[i]= get_v(bc);
875
        nut->stream[stream_id].initial_pts_predictor[i]= get_v(bc);
876
    nut->stream[stream_id].decode_delay= get_v(bc);
926 877
    get_byte(bc); /* flags */
927 878

  
928 879
    /* codec specific data headers */
......
946 897
    }
947 898
    if (class == 32) /* AUDIO */
948 899
    {
949
        st->codec.sample_rate = (get_v(bc) * nom) / denom;
900
        st->codec.sample_rate = get_v(bc);
901
        get_v(bc); // samplerate_den
950 902
        st->codec.channels = get_v(bc);
951 903
    }
952 904
    if(check_checksum(bc)){
......
962 914
    AVFormatContext *s= nut->avf;
963 915
    ByteIOContext *bc = &s->pb;
964 916
    
965
    get_packetheader(nut, bc, 8, 1);
917
    get_packetheader(nut, bc, 1);
966 918

  
967 919
    for(;;){
968 920
        int id= get_v(bc);
......
1072 1024
    return 0;
1073 1025
}
1074 1026

  
1075
static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code, int frame_type){
1027
static int decode_frame_header(NUTContext *nut, int *key_frame_ret, int64_t *pts_ret, int *stream_id_ret, int frame_code, int frame_type){
1076 1028
    AVFormatContext *s= nut->avf;
1077 1029
    StreamContext *stream;
1078 1030
    ByteIOContext *bc = &s->pb;
1079 1031
    int size, flags, size_mul, size_lsb, stream_id;
1080
    int key_frame = 0;
1081 1032
    int64_t pts = 0;
1082 1033
    const int prefix_len= frame_type == 2 ? 8+1 : 1;
1083 1034
    const int64_t frame_start= url_ftell(bc) - prefix_len;
1084 1035

  
1036
    if(frame_type < 2 && frame_start - nut->packet_start[2] > nut->max_distance){
1037
        av_log(s, AV_LOG_ERROR, "last frame must have been damaged\n");
1038
        return -1;
1039
    }
1040

  
1041
    if(frame_type)
1042
        nut->packet_start[ frame_type ]= frame_start; //otherwise 1 goto 1 may happen
1043
    
1085 1044
    flags= nut->frame_code[frame_code].flags;
1086 1045
    size_mul= nut->frame_code[frame_code].size_mul;
1087 1046
    size_lsb= nut->frame_code[frame_code].size_lsb;
1088 1047
    stream_id= nut->frame_code[frame_code].stream_id_plus1 - 1;
1089 1048

  
1090
    if(flags & FLAG_FRAME_TYPE){
1049
    if(frame_type == 2)
1091 1050
        reset(s);
1092
        if(get_packetheader(nut, bc, prefix_len, 0) < 0)
1093
            return -1;
1094
        if(frame_type!=2)
1095
            frame_type= 1;
1096
    }
1097 1051

  
1098 1052
    if(stream_id==-1)
1099 1053
        stream_id= get_v(bc);
......
1104 1058
    stream= &nut->stream[stream_id];
1105 1059

  
1106 1060
//    av_log(s, AV_LOG_DEBUG, "ft:%d ppts:%d %d %d\n", frame_type, stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);
1107
    
1108
    key_frame= !!(flags & FLAG_KEY_FRAME);
1109

  
1110
    if(flags & FLAG_PTS){
1111
        if(flags & FLAG_FULL_PTS){
1112
            pts= get_v(bc);
1113
            if(frame_type && key_frame){
1114
                int64_t av_pts= pts * AV_TIME_BASE * stream->rate_den / stream->rate_num;
1115
                av_add_index_entry(
1116
                    s->streams[stream_id], 
1117
                    frame_start, 
1118
                    av_pts, 
1119
                    frame_start - nut->stream[stream_id].last_sync_pos,
1120
                    AVINDEX_KEYFRAME);
1121
                nut->stream[stream_id].last_sync_pos= frame_start;
1122
                assert(nut->packet_start == frame_start);
1123
            }
1061

  
1062
    *key_frame_ret= !!(flags & FLAG_KEY_FRAME);
1063

  
1064
    if((flags & FLAG_PTS) == FLAG_PTS){
1065
        int64_t mask = (1<<stream->msb_timestamp_shift)-1;
1066
        pts= get_v(bc);
1067
        if(pts > mask){
1068
            pts -= mask+1;
1124 1069
        }else{
1125
            int64_t mask = (1<<stream->msb_timestamp_shift)-1;
1126
            int64_t delta= stream->last_pts - mask/2;
1127
            pts= ((get_v(bc) - delta)&mask) + delta;
1070
            if(stream->last_pts == AV_NOPTS_VALUE){
1071
                av_log(s, AV_LOG_ERROR, "no reference pts available\n");
1072
                return -1;
1073
            }
1074
            pts= lsb2full(stream, pts);
1128 1075
        }
1129 1076
    }else{
1130
        pts= stream->last_pts + stream->lru_pts_delta[(flags&12)>>2];
1077
        if(stream->last_pts == AV_NOPTS_VALUE){
1078
            av_log(s, AV_LOG_ERROR, "no reference pts available\n");
1079
            return -1;
1080
        }
1081
        pts= stream->last_pts + stream->lru_pts_delta[flags&FLAG_PTS];
1131 1082
    }
1132
  
1133
    if(size_mul <= size_lsb){
1134
        size= stream->lru_size[size_lsb - size_mul];
1135
    }else{
1136
        if(flags & FLAG_DATA_SIZE)
1137
            size= size_mul*get_v(bc) + size_lsb;
1138
        else
1139
            size= size_lsb;
1083

  
1084
    if(*key_frame_ret){
1085
        int64_t av_pts= pts * AV_TIME_BASE * stream->rate_den / stream->rate_num;
1086
//        av_log(s, AV_LOG_DEBUG, "stream:%d start:%lld pts:%lld length:%lld\n",stream_id, frame_start, av_pts, frame_start - nut->stream[stream_id].last_sync_pos);
1087
        av_add_index_entry(
1088
            s->streams[stream_id], 
1089
            frame_start, 
1090
            av_pts, 
1091
            frame_start - nut->stream[stream_id].last_sync_pos,
1092
            AVINDEX_KEYFRAME);
1093
        nut->stream[stream_id].last_sync_pos= frame_start;
1094
//                assert(nut->packet_start == frame_start);
1140 1095
    }
1096

  
1097
    assert(size_mul > size_lsb);
1098
    size= size_lsb;
1099
    if(flags & FLAG_DATA_SIZE)
1100
        size+= size_mul*get_v(bc);
1141 1101
      
1142 1102
//av_log(s, AV_LOG_DEBUG, "fs:%lld fc:%d ft:%d kf:%d pts:%lld size:%d\n", frame_start, frame_code, frame_type, key_frame, pts, size);
1143 1103

  
1144
    if(url_ftell(bc) - nut->packet_start + size > nut->written_packet_size){
1104
    if(frame_type==0 && url_ftell(bc) - nut->packet_start[2] + size > nut->max_distance){
1145 1105
        av_log(s, AV_LOG_ERROR, "frame size too large\n");
1146 1106
        return -1;
1147 1107
    }
1148 1108
    
1109
    *stream_id_ret = stream_id;
1110
    *pts_ret = pts * AV_TIME_BASE * stream->rate_den / stream->rate_num;
1111

  
1112
    update(nut, stream_id, frame_start, frame_type, frame_code, *key_frame_ret, size, pts);
1113

  
1114
    return size;
1115
}
1116

  
1117
static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code, int frame_type){
1118
    AVFormatContext *s= nut->avf;
1119
    ByteIOContext *bc = &s->pb;
1120
    int size, stream_id, key_frame;
1121
    int64_t pts;
1122
    
1123
    size= decode_frame_header(nut, &key_frame, &pts, &stream_id, frame_code, frame_type);
1124
    if(size < 0)
1125
        return -1;
1126

  
1149 1127
    av_new_packet(pkt, size);
1150 1128
    get_buffer(bc, pkt->data, size);
1151 1129
    pkt->stream_index = stream_id;
1152 1130
    if (key_frame)
1153 1131
	pkt->flags |= PKT_FLAG_KEY;
1154
    pkt->pts = pts * AV_TIME_BASE * stream->rate_den / stream->rate_num;
1132
    pkt->pts = pts;
1155 1133

  
1156
    update(nut, stream_id, frame_start, frame_type, frame_code, key_frame, size, pts);
1157
    
1158 1134
    return 0;
1159 1135
}
1160 1136

  
......
1162 1138
{
1163 1139
    NUTContext *nut = s->priv_data;
1164 1140
    ByteIOContext *bc = &s->pb;
1165
    int size, i, frame_code=0;
1166
    int64_t pos;
1141
    int i, frame_code=0;
1167 1142

  
1168 1143
    for(;;){
1169 1144
        int frame_type= 0;
......
1185 1160
        case MAIN_STARTCODE:
1186 1161
        case STREAM_STARTCODE:
1187 1162
        case INDEX_STARTCODE:
1188
            get_packetheader(nut, bc, 8, 0);
1189
            url_fseek(bc, nut->written_packet_size + nut->packet_start, SEEK_SET);
1163
            get_packetheader(nut, bc, 0);
1164
            url_fseek(bc, nut->written_packet_size + nut->packet_start[2], SEEK_SET);
1190 1165
            break;
1191 1166
        case INFO_STARTCODE:
1192 1167
            if(decode_info_header(nut)<0)
......
1200 1175
                return 0;
1201 1176
        default:
1202 1177
resync:
1203
av_log(s, AV_LOG_DEBUG, "syncing from %lld\n", nut->packet_start+1);
1204
            tmp= find_any_startcode(bc, nut->packet_start+1);
1178
av_log(s, AV_LOG_DEBUG, "syncing from %lld\n", nut->packet_start[2]+1);
1179
            tmp= find_any_startcode(bc, nut->packet_start[2]+1);
1205 1180
            if(tmp==0)
1206 1181
                return -1;
1207 1182
av_log(s, AV_LOG_DEBUG, "sync\n");
1208
            if(url_is_streamed(bc)){
1209
                nut->next_startcode= tmp;
1210
                break;
1211
            }
1212

  
1213
            pos= url_ftell(bc) - 8;
1214
av_log(s, AV_LOG_DEBUG, "at %lld code=%llX\n", pos, tmp);
1215
            if(tmp==KEYFRAME_STARTCODE){
1216
                get_byte(bc);
1217
            }
1218
            get_v(bc);
1219
            size= get_v(bc);
1220
            
1221
            while(size > 2 && size < 100000 && nut->packet_start < pos - size){
1222
                url_fseek(bc, pos - size, SEEK_SET);
1223
                frame_code= get_byte(bc);
1224
                if(!(nut->frame_code[ frame_code ].flags & FLAG_FRAME_TYPE))
1225
                    break;
1226
                if(get_v(bc) != size)
1227
                    break;
1228
                pos -= size;
1229
                size= get_v(bc);
1230
av_log(s, AV_LOG_DEBUG, "steping back to %lld next %d\n", pos, size);
1231
            }
1232
            url_fseek(bc, pos, SEEK_SET);
1233
            
1234
            nut->written_packet_size= -1;
1183
            nut->next_startcode= tmp;
1235 1184
        }
1236 1185
    }
1237 1186
}
......
1242 1191
    ByteIOContext *bc = &s->pb;
1243 1192
    int64_t pos, pts;
1244 1193
    uint64_t code;
1245
    int frame_code,step, flags, stream_id, i;
1194
    int frame_code,step, stream_id, i,size, key_frame;
1246 1195
av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%lld,%lld)\n", stream_index, *pos_arg, pos_limit);
1247 1196

  
1248 1197
    if(*pos_arg < 0)
1249 1198
        return AV_NOPTS_VALUE;
1250 1199

  
1251
    // find a previous startcode, FIXME use forward search and follow backward pointers if undamaged stream
1252 1200
    pos= *pos_arg;
1253 1201
    step= FFMIN(16*1024, pos);
1254 1202
    do{
1255 1203
        pos-= step;
1256 1204
        code= find_any_startcode(bc, pos);
1257 1205

  
1258
        if(code && url_ftell(bc) - 8 < *pos_arg)
1206
        if(code && url_ftell(bc) - 8 <= *pos_arg)
1259 1207
            break;
1260 1208
        step= FFMIN(2*step, pos);
1261 1209
    }while(step);
......
1268 1216
        nut->stream[i].last_sync_pos= url_ftell(bc);
1269 1217
        
1270 1218
    for(;;){
1219
        int frame_type=0;
1271 1220
        int64_t pos= url_ftell(bc);
1272 1221
        uint64_t tmp=0;
1273
        int prefix_len=1;
1274 1222
        
1275
        if(pos > pos_limit)
1223
        if(pos > pos_limit || url_feof(bc))
1276 1224
            return AV_NOPTS_VALUE;
1277 1225

  
1278 1226
        frame_code = get_byte(bc);
......
1288 1236
        case STREAM_STARTCODE:
1289 1237
        case INDEX_STARTCODE:
1290 1238
        case INFO_STARTCODE:
1291
            nut->written_packet_size= -1;
1292
            get_packetheader(nut, bc, 8, 0);
1293
            url_fseek(bc, nut->written_packet_size + nut->packet_start, SEEK_SET);
1239
            get_packetheader(nut, bc, 0);
1240
            assert(nut->packet_start[2]==pos);
1241
            url_fseek(bc, nut->written_packet_size + pos, SEEK_SET);
1294 1242
            break;
1295 1243
        case KEYFRAME_STARTCODE:
1296
            nut->written_packet_size= -1;
1297
            prefix_len+=8;
1244
            frame_type=2;
1298 1245
            frame_code = get_byte(bc);
1299 1246
        case 0:
1300
            flags= nut->frame_code[frame_code].flags;
1301
            stream_id= nut->frame_code[frame_code].stream_id_plus1 - 1;
1302

  
1303
            if(get_packetheader(nut, bc, prefix_len, 0) < 0)
1304
                goto resync;
1305

  
1306
            if(!(flags & FLAG_FRAME_TYPE) || !(flags & FLAG_PTS) || !(flags & FLAG_FULL_PTS))
1307
                goto resync;
1308

  
1309
            if(stream_id==-1)
1310
                stream_id= get_v(bc);
1311
            if(stream_id >= s->nb_streams)
1247
            size= decode_frame_header(nut, &key_frame, &pts, &stream_id, frame_code, frame_type);
1248
            if(size < 0)
1312 1249
                goto resync;
1313 1250
                
1314 1251
            stream= &nut->stream[stream_id];
1315
            pts= get_v(bc) * AV_TIME_BASE * stream->rate_den / stream->rate_num;
1316
    
1317
            if(flags & FLAG_KEY_FRAME){
1318
                av_add_index_entry(
1319
                    s->streams[stream_id], 
1320
                    pos, 
1321
                    pts, 
1322
                    pos - nut->stream[stream_id].last_sync_pos,
1323
                    AVINDEX_KEYFRAME);
1324
                nut->stream[stream_id].last_sync_pos= pos;
1325
            }
1326
            if(stream_id != stream_index || !(flags & FLAG_KEY_FRAME) || nut->packet_start < *pos_arg){
1327
                url_fseek(bc, nut->written_packet_size + nut->packet_start, SEEK_SET);
1252
            if(stream_id != stream_index || !key_frame || pos < *pos_arg){
1253
                url_fseek(bc, size, SEEK_CUR);
1328 1254
                break;
1329 1255
            }
1330 1256
 
1331
            *pos_arg= nut->packet_start;
1332
            assert(nut->packet_start == pos);
1257
            *pos_arg= pos;
1333 1258
            return pts;
1334 1259
        default:
1335 1260
resync:
1336
av_log(s, AV_LOG_DEBUG, "syncing from %lld\n", nut->packet_start+1);
1337
            if(!find_any_startcode(bc, nut->packet_start+1))
1261
av_log(s, AV_LOG_DEBUG, "syncing from %lld\n", nut->packet_start[2]+1);
1262
            if(!find_any_startcode(bc, nut->packet_start[2]+1))
1338 1263
                return AV_NOPTS_VALUE;
1339 1264

  
1340 1265
            url_fseek(bc, -8, SEEK_CUR);
......
1344 1269
}
1345 1270

  
1346 1271
static int nut_read_seek(AVFormatContext *s, int stream_index, int64_t target_ts){
1347
    NUTContext *nut = s->priv_data;
1272
//    NUTContext *nut = s->priv_data;
1348 1273
    int64_t pos;
1349
    int i;
1350 1274

  
1351 1275
    if(av_seek_frame_binary(s, stream_index, target_ts) < 0)
1352 1276
        return -1;
1353 1277

  
1354
    nut->written_packet_size= -1;
1355 1278
    pos= url_ftell(&s->pb);
1356
    for(i=0; i<s->nb_streams; i++)
1357
        nut->stream[i].last_sync_pos= pos;
1279
    nut_read_timestamp(s, stream_index, &pos, pos-1);
1358 1280

  
1359 1281
    return 0;
1360 1282
}

Also available in: Unified diff