Statistics
| Branch: | Tag: | Revision:

dvbd / remux.c @ bfdb7446

History | View | Annotate | Download (26.8 KB)

1
/*
2
  Copyright 2003 John Knottenbelt
3
  
4
  This program is free software; you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation; either version 2 of the License, or
7
  (at your option) any later version.
8
 
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
 
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17
*/
18

    
19
#include "config.h"
20
#include "remux.h"
21

    
22
unsigned int bitrates[3][16] =
23
{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
24
 {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
25
 {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
26

    
27
uint32_t freq[4] = {441, 480, 320, 0};
28
static uint32_t samples[4] = { 384, 1152, 0, 0};
29
char *frames[3] = {"I-Frame","P-Frame","B-Frame"};
30

    
31

    
32
void copy_ptslm(PTS_List *a, PTS_List *b)
33
{
34
        a->pos  = b->pos;
35
        a->PTS  = b->PTS;
36
        a->dts  = b->dts;
37
        a->spos = b->spos;
38
}
39

    
40
void clear_ptslm(PTS_List *a)
41
{
42
        a->pos  = 0;
43
        a->PTS  = 0;
44
        a->dts  = 0;
45
        a->spos = 0;        
46
}
47

    
48
void init_ptsl(PTS_List *ptsl)
49
{
50
        int i;
51
        for (i=0;i< MAX_PTS;i++){
52
                clear_ptslm(&ptsl[i]);
53
        }
54
}
55

    
56
int del_pts(PTS_List *ptsl, int pos, int nr)
57
{
58
        int i;
59
        int del = 0;
60

    
61
        for( i = 0; i < nr-1; i++){
62
                if(pos > ptsl[i].pos && pos >= ptsl[i+1].pos) del++;
63
        }
64

    
65
        if(del)
66
                for( i = 0; i < nr-del; i++){
67
                        copy_ptslm(&ptsl[i], &ptsl[i+del]);
68
                }
69

    
70
        return nr-del;
71
}
72

    
73
int del_ptss(PTS_List *ptsl, int pts, int *nb)
74
{
75
        int i;
76
        int del = 0;
77
        int sum = 0;
78
        int nr = *nb;
79

    
80
        for( i = 0; i < nr; i++){
81
                if(pts > ptsl[i].PTS){
82
                        del++;
83
                        sum += ptsl[i].pos;
84
                }
85
        }
86

    
87
        if(del)
88
                for( i = 0; i < nr-del; i++){
89
                        copy_ptslm(&ptsl[i], &ptsl[i+del]);
90
                }
91

    
92
        *nb = nr-del;
93
        return sum;
94
}
95

    
96
int add_pts(PTS_List *ptsl, uint32_t pts, int pos, int spos, int nr, uint32_t dts)
97
{
98
        int i;
99

    
100
        for ( i=0;i < nr; i++) if (spos &&  ptsl[i].pos == pos) return nr;
101
        if (nr == MAX_PTS) {
102
                nr = del_pts(ptsl, ptsl[1].pos+1, nr);
103
        } else nr++;
104
        i = nr-1;
105
        
106
        ptsl[i].pos  = pos;
107
        ptsl[i].spos = spos;
108
        ptsl[i].PTS  = pts;
109
        ptsl[i].dts  = dts;
110
        return nr;
111
}
112

    
113
void add_vpts(Remux *rem, uint8_t *pts)
114
{
115
        uint32_t PTS = ntohl(trans_pts_dts(pts));
116
        rem->vptsn = add_pts(rem->vpts_list, PTS, rem->vwrite, rem->awrite,
117
                             rem->vptsn, PTS);
118
}
119

    
120
void add_apts(Remux *rem, uint8_t *pts)
121
{
122
        uint32_t PTS = ntohl(trans_pts_dts(pts));
123
        rem->aptsn = add_pts(rem->apts_list, PTS, rem->awrite, rem->vwrite,
124
                             rem->aptsn, PTS);
125
}
126

    
127
void del_vpts(Remux *rem)
128
{
129
        rem->vptsn = del_pts(rem->vpts_list, rem->vread, rem->vptsn);
130
}
131

    
132
void del_apts(Remux *rem)
133
{
134
        rem->aptsn = del_pts(rem->apts_list, rem->aread, rem->aptsn);
135
}
136

    
137

    
138
void copy_framelm(FRAME_List *a, FRAME_List *b)
139
{
140
        a->type  = b->type;
141
        a->pos   = b->pos;
142
        a->FRAME = b->FRAME;
143
        a->time  = b->time;
144
        a->pts   = b->pts;
145
        a->dts   = b->dts;
146
}
147

    
148
void clear_framelm(FRAME_List *a)
149
{
150
        a->type  = 0;
151
        a->pos   = 0;
152
        a->FRAME = 0;
153
        a->time  = 0; 
154
        a->pts   = 0; 
155
        a->dts   = 0; 
156
}
157

    
158
void init_framel(FRAME_List *framel)
159
{
160
        int i;
161
        for (i=0;i< MAX_FRAME;i++){
162
                clear_framelm(&framel[i]);
163
        }
164
}
165

    
166
int del_frame(FRAME_List *framel, int pos, int nr)
167
{
168
        int i;
169
        int del = 0;
170

    
171
        for( i = 0; i < nr-1; i++){
172
                if(pos > framel[i].pos && pos >= framel[i+1].pos) del++;
173
        }
174

    
175
        if(del)
176
                for( i = 0; i < nr-del; i++){
177
                        copy_framelm(&framel[i], &framel[i+del]);
178
                }
179

    
180
        return nr-del;
181
}
182

    
183
int add_frame(FRAME_List *framel, uint32_t frame, int pos, int type, int nr, 
184
              uint32_t time, uint32_t pts, uint32_t dts)
185
{
186
        int i;
187

    
188
        if (nr == MAX_FRAME) {
189
                nr = del_frame(framel, framel[1].pos+1, nr);
190
        } else nr++;
191
        i = nr-1;
192
        
193
        framel[i].type  = type;
194
        framel[i].pos   = pos;
195
        framel[i].FRAME = frame;
196
        framel[i].time  = time;
197
        framel[i].pts   = pts;
198
        framel[i].dts   = dts;
199
        return nr;
200
}
201

    
202
void add_vframe(Remux *rem, uint32_t frame, long int pos, int type, int time, 
203
                uint32_t pts, uint32_t dts)
204
{
205
        rem->vframen = add_frame(rem->vframe_list, frame, pos, type,
206
                                 rem->vframen, time, pts, dts);
207
}
208

    
209
void add_aframe(Remux *rem, uint32_t frame, long int pos, uint32_t pts)
210
{
211
        rem->aframen = add_frame(rem->aframe_list, frame, pos, 0, 
212
                                 rem->aframen, 0, pts, pts);
213
}
214

    
215
void del_vframe(Remux *rem)
216
{
217
        rem->vframen = del_frame(rem->vframe_list, rem->vread, rem->vframen);
218
}
219

    
220
void del_aframe(Remux *rem)
221
{
222
        rem->aframen = del_frame(rem->aframe_list, rem->aread, rem->aframen);
223
}
224

    
225

    
226
void printpts(uint32_t pts)
227
{
228
        fprintf(stderr,"%2d:%02d:%02d.%03d",
229
                (int)(pts/90000.)/3600,
230
                ((int)(pts/90000.)%3600)/60,
231
                ((int)(pts/90000.)%3600)%60,
232
                (((int)(pts/90.)%3600000)%60000)%1000
233
                );
234
}
235

    
236

    
237
void find_vframes( Remux *rem, uint8_t *buf, int l)
238
{
239
         int c = 0;
240
        int type;
241
        uint32_t time = 0;
242
        int hour;
243
        int min;
244
        int sec;
245
        u64 pts=0;
246
        u64 dts=0;
247
        uint32_t tempref = 0;
248

    
249
        while ( c < l - 6){
250
                if (buf[c] == 0x00 && 
251
                    buf[c+1] == 0x00 &&
252
                    buf[c+2] == 0x01 && 
253
                    buf[c+3] == 0xB8) {
254
                        c += 4;
255
                        hour = (int)((buf[c]>>2)& 0x1F);
256
                        min  = (int)(((buf[c]<<4)& 0x30)| 
257
                                     ((buf[c+1]>>4)& 0x0F));
258
                        sec  = (int)(((buf[c+1]<<3)& 0x38)|
259
                                      ((buf[c+2]>>5)& 0x07));
260
  
261
                        time = 3600*hour + 60*min + sec;
262
                        if ( rem->time_off){
263
                                time = (uint32_t)((u64)time - rem->time_off);
264
                                hour = time/3600;
265
                                min  = (time%3600)/60;
266
                                sec  = (time%3600)%60;
267
                                /*
268
                                buf[c]   |= (hour & 0x1F) << 2;
269
                                buf[c]   |= (min & 0x30) >> 4;
270
                                buf[c+1] |= (min & 0x0F) << 4;
271
                                buf[c+1] |= (sec & 0x38) >> 3;
272
                                buf[c+2] |= (sec & 0x07) >> 5;*/
273
                        }
274
                        rem->group++;
275
                        rem->groupframe = 0;
276
                }
277
                if ( buf[c] == 0x00 && 
278
                     buf[c+1] == 0x00 &&
279
                     buf[c+2] == 0x01 && 
280
                     buf[c+3] == 0x00) {
281
                        c += 4;
282
                        tempref = (buf[c+1]>>6) & 0x03;
283
                        tempref |= buf[c] << 2;
284
                        
285
                        type = ((buf[c+1]&0x38) >>3);
286
                        if ( rem->video_info.framerate){
287
                                pts = ((u64)rem->vframe + tempref + 1 
288
                                        - rem->groupframe ) * 90000ULL
289
                                            /rem->video_info.framerate 
290
                                        + rem->vpts_off;
291
                                dts = (u64)rem->vframe * 90000ULL/
292
                                        rem->video_info.framerate 
293
                                        + rem->vpts_off;
294
                        
295
                                /*        
296
fprintf(stderr,"MYPTS:");
297
printpts((uint32_t)pts-rem->vpts_off);
298
 fprintf(stderr,"   REALPTS:");
299
 printpts(rem->vpts_list[rem->vptsn-1].PTS-rem->vpts_off);
300
 fprintf(stderr,"   DIFF:");
301
 printpts(pts-(u64)rem->vpts_list[rem->vptsn-1].PTS);
302
 fprintf(stderr,"   DIST: %4d",-rem->vpts_list[rem->vptsn-1].pos+(rem->vwrite+c-4));
303
 //fprintf(stderr,"   ERR: %3f",(double)(-rem->vpts_list[rem->vptsn-1].PTS+pts)/(rem->vframe+1));
304
 fprintf(stderr,"\r");
305
                                */
306
                                
307
                                
308
                                rem->vptsn = add_pts(rem->vpts_list,(uint32_t)pts
309
                                                     ,rem->vwrite+c-4,
310
                                                     rem->awrite,
311
                                                     rem->vptsn,
312
                                                     (uint32_t)dts);
313

    
314
                                
315
                                
316
                        }
317
                        rem->vframe++;
318
                        rem->groupframe++;
319
                        add_vframe( rem, rem->vframe, rem->vwrite+c, type, 
320
                                    time, pts, dts);
321
                } else c++;
322
        }
323
}
324

    
325
void find_aframes( Remux *rem, uint8_t *buf, int l)
326
{
327
         int c = 0;
328
        u64 pts = 0;
329
        int sam;
330
        uint32_t fr;
331

    
332

    
333
        while ( c < l - 2){
334
                if ( buf[c] == 0xFF && 
335
                     (buf[c+1] & 0xF8) == 0xF8) {
336
                        c += 2;
337
                        if ( rem->audio_info.layer >= 0){
338
                                sam = samples[3-rem->audio_info.layer];
339
                                fr = freq[rem->audio_info.frequency] ;
340
                
341
                          pts = ( (u64)rem->aframe * sam * 900ULL)/fr
342
                                  + rem->apts_off;
343
                                
344
                          /*            
345
fprintf(stderr,"MYPTS:");
346
printpts((uint32_t)pts-rem->apts_off);
347
 fprintf(stderr," REALPTS:");
348
 printpts(rem->apts_list[rem->aptsn-1].PTS-rem->apts_off);
349
 fprintf(stderr," DIFF:");
350
 printpts((uint32_t)((u64)rem->apts_list[rem->aptsn-1].PTS-pts));
351
 fprintf(stderr," DIST: %4d",-rem->apts_list[rem->aptsn-1].pos+(rem->awrite+c-2));
352
 fprintf(stderr,"\r");
353
                          */
354
                          rem->aptsn = add_pts(rem->apts_list,(uint32_t)pts
355
                                             ,rem->awrite+c-2,
356
                                             rem->vwrite,
357
                                             rem->aptsn,
358
                                             (uint32_t)pts);
359
                }
360

    
361
                        rem->aframe++;
362
                        add_aframe( rem, rem->aframe, rem->awrite+c, pts);
363
                        
364
                } else c++;
365
        }
366
}
367

    
368
int refill_buffy(Remux *rem)
369
{
370
        pes_packet pes;
371
        int count = 0;
372
        int acount, vcount;
373
        ringbuffy *vbuf = &rem->vid_buffy;
374
        ringbuffy *abuf = &rem->aud_buffy;
375
        int fin = rem->fin;
376

    
377
        acount = abuf->size-ring_rest(abuf);
378
        vcount = vbuf->size-ring_rest(vbuf);
379
        
380
        
381
        while ( acount > MAX_PLENGTH && vcount > MAX_PLENGTH && count < 10){
382
                int neof;
383
                count++;
384
                init_pes(&pes);
385
                if ((neof = read_pes(fin,&pes)) <= 0) return -1;
386
                switch(pes.stream_id){
387
                case AUDIO_STREAM_S ... AUDIO_STREAM_E:
388
                        rem->apes++;
389
                        if( rem->audio_info.layer < 0 &&
390
                            (pes.flags2 & PTS_DTS) )
391
                                add_apts(rem, pes.pts);
392
                        find_aframes( rem, pes.pes_pckt_data, pes.length);
393
                        ring_write(abuf,(char *)pes.pes_pckt_data,pes.length);
394
                        rem->awrite += pes.length;
395
                        break;
396
                case VIDEO_STREAM_S ... VIDEO_STREAM_E:
397
                        rem->vpes++;
398
                        if( !rem->video_info.framerate &&
399
                            (pes.flags2 & PTS_DTS) )
400
                                add_vpts(rem, pes.pts);
401

    
402
                        find_vframes( rem, pes.pes_pckt_data, pes.length);
403

    
404
                        ring_write(vbuf,(char *)pes.pes_pckt_data,pes.length);
405
                        rem->vwrite += pes.length;
406
                        break;
407
                }
408
                acount = abuf->size-ring_rest(abuf);
409
                vcount = vbuf->size-ring_rest(vbuf);
410
                kill_pes(&pes);
411
        }
412
        if (count < 10)        return 0;
413
        return 1;
414
}
415

    
416
int vring_read( Remux *rem, uint8_t *buf, int l)
417
{
418
        int c = 0;
419
        int r = 0;
420

    
421
        if (ring_rest(&rem->vid_buffy) <= l)
422
                r = refill_buffy(rem);
423
        if (r) return -1;
424

    
425
        c = ring_read(&rem->vid_buffy, (char *) buf, l);
426
        rem->vread += c;
427
        del_vpts(rem);
428
        del_vframe(rem);
429
        return c;
430
}
431

    
432
int aring_read( Remux *rem, uint8_t *buf, int l)
433
{
434
        int c = 0;
435
        int r = 0;
436

    
437
        if (ring_rest(&rem->aud_buffy) <= l)
438
                r = refill_buffy(rem);
439
        if (r) return -1;
440
        
441
        c = ring_read(&rem->aud_buffy, (char *)buf, l);
442
        rem->aread += c;
443
        del_apts(rem);
444
        del_aframe(rem);
445
        return c;
446
}
447

    
448
int vring_peek( Remux *rem, uint8_t *buf, int l, long off)
449
{
450
        int c = 0;
451
        
452
        if (ring_rest(&rem->vid_buffy) <= l)
453
                refill_buffy(rem);
454

    
455
        c = ring_peek(&rem->vid_buffy, (char *) buf, l, off);
456
        return c;
457
}
458

    
459
int aring_peek( Remux *rem, uint8_t *buf, int l, long off)
460
{
461
        int c = 0;
462

    
463
        if (ring_rest(&rem->aud_buffy) <= l)
464
                refill_buffy(rem);
465

    
466
        c = ring_peek(&rem->aud_buffy, (char *)buf, l, off);
467
        return c;
468
}
469

    
470

    
471
int get_video_info(Remux *rem)
472
{
473
        uint8_t buf[12];
474
        uint8_t *headr;
475
        int found = 0;
476
        int sw;
477
        long off = 0;
478
        int form = -1;
479
        ringbuffy *vid_buffy = &rem->vid_buffy;
480
        VideoInfo *vi = &rem->video_info;
481

    
482
        while (found < 4 && ring_rest(vid_buffy)){
483
                uint8_t b[3];
484

    
485
                vring_peek( rem, b, 4, 0);
486
                if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
487
                     && b[3] == 0xb3) found = 4;
488
                else {
489
                        off++;
490
                        vring_read( rem, b, 1);
491
                }
492
        }
493
        rem->vframe = rem->vframen-1;
494

    
495
        if (! found) return -1;
496
        buf[0] = 0x00; buf[1] = 0x00; buf[2] = 0x01; buf[3] = 0xb3;
497
        headr = buf+4;
498
        if(vring_peek(rem, buf, 12, 0) < 12) return -1;
499

    
500
        vi->horizontal_size        = ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
501
        vi->vertical_size        = ((headr[1] &0x0F) << 8) | (headr[2]);
502
    
503
        sw = (int)((headr[3]&0xF0) >> 4) ;
504

    
505
        switch( sw ){
506
        case 1:
507
                fprintf(stderr,"Videostream: ASPECT: 1:1");
508
                vi->aspect_ratio = 100;        
509
                break;
510
        case 2:
511
                fprintf(stderr,"Videostream: ASPECT: 4:3");
512
                vi->aspect_ratio = 133;        
513
                break;
514
        case 3:
515
                fprintf(stderr,"Videostream: ASPECT: 16:9");
516
                vi->aspect_ratio = 177;        
517
                break;
518
        case 4:
519
                fprintf(stderr,"Videostream: ASPECT: 2.21:1");
520
                vi->aspect_ratio = 221;        
521
                break;
522

    
523
        case 5 ... 15:
524
                fprintf(stderr,"Videostream: ASPECT: reserved");
525
                vi->aspect_ratio = 0;        
526
                break;
527

    
528
        default:
529
                vi->aspect_ratio = 0;        
530
                return -1;
531
        }
532

    
533
        fprintf(stderr,"  Size = %dx%d",vi->horizontal_size,vi->vertical_size);
534

    
535
        sw = (int)(headr[3]&0x0F);
536

    
537
        switch ( sw ) {
538
        case 1:
539
                fprintf(stderr,"  FRate: 23.976 fps");
540
                vi->framerate = 24000/1001.;
541
                form = -1;
542
                break;
543
        case 2:
544
                fprintf(stderr,"  FRate: 24 fps");
545
                vi->framerate = 24;
546
                form = -1;
547
                break;
548
        case 3:
549
                fprintf(stderr,"  FRate: 25 fps");
550
                vi->framerate = 25;
551
                form = VIDEO_MODE_PAL;
552
                break;
553
        case 4:
554
                fprintf(stderr,"  FRate: 29.97 fps");
555
                vi->framerate = 30000/1001.;
556
                form = VIDEO_MODE_NTSC;
557
                break;
558
        case 5:
559
                fprintf(stderr,"  FRate: 30 fps");
560
                vi->framerate = 30;
561
                form = VIDEO_MODE_NTSC;
562
                break;
563
        case 6:
564
                fprintf(stderr,"  FRate: 50 fps");
565
                vi->framerate = 50;
566
                form = VIDEO_MODE_PAL;
567
                break;
568
        case 7:
569
                fprintf(stderr,"  FRate: 60 fps");
570
                vi->framerate = 60;
571
                form = VIDEO_MODE_NTSC;
572
                break;
573
        }
574

    
575
        rem->dts_delay = (int)(7.0/vi->framerate/2.0*90000);
576

    
577
        vi->bit_rate = 400*(((headr[4] << 10) & 0x0003FC00UL) 
578
                            | ((headr[5] << 2) & 0x000003FCUL) | 
579
                            (((headr[6] & 0xC0) >> 6) & 0x00000003UL));
580
        
581
        fprintf(stderr,"  BRate: %.2f Mbit/s",(vi->bit_rate)/1000000.);
582
        
583
        fprintf(stderr,"\n");
584
        vi->video_format = form;
585

    
586
        /*
587
        marker_bit (&video_bs, 1);
588
        vi->vbv_buffer_size        = getbits (&video_bs, 10);
589
        vi->CSPF                = get1bit (&video_bs);
590
        */
591
        return form;
592
}
593

    
594

    
595
int get_audio_info( Remux *rem)
596
{
597
        uint8_t *headr;
598
        uint8_t buf[3];
599
        long off = 0;
600
        int found = 0;
601
        ringbuffy *aud_buffy = &rem->aud_buffy;
602
        AudioInfo *ai = &rem->audio_info;
603
        
604
        while(!ring_rest(aud_buffy) && !refill_buffy(rem));
605
        while (found < 2 && ring_rest(aud_buffy)){
606
                uint8_t b[2];
607
                refill_buffy(rem);
608
                aring_peek( rem, b, 2, 0);
609

    
610
                if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
611
                        found = 2;
612
                else {
613
                        off++;
614
                        aring_read( rem, b, 1);
615
                }
616
        }        
617

    
618
        if (!found) return -1;
619
        rem->aframe = rem->aframen-1;
620
        
621
        if (aring_peek(rem, buf, 3, 0) < 1) return -1;
622
        headr = buf+2;
623

    
624
        ai->layer = (buf[1] & 0x06) >> 1;
625

    
626
        fprintf(stderr,"Audiostream: Layer: %d", 4-ai->layer);
627

    
628

    
629
        ai->bit_rate = bitrates[(3-ai->layer)][(headr[0] >> 4 )]*1000;
630

    
631
        if (ai->bit_rate == 0)
632
                fprintf (stderr,"  Bit rate: free");
633
        else if (ai->bit_rate == 0xf)
634
                fprintf (stderr,"  BRate: reserved");
635
        else
636
                fprintf (stderr,"  BRate: %d kb/s", ai->bit_rate/1000);
637
        
638

    
639
        ai->frequency = (headr[0] & 0x0c ) >> 2;
640
        if (ai->frequency == 3)
641
                fprintf (stderr, "  Freq: reserved\n");
642
        else
643
                fprintf (stderr,"  Freq: %2.1f kHz\n", 
644
                         freq[ai->frequency]/10.);
645

    
646
        return 0;
647
}
648

    
649

    
650

    
651
void init_remux(Remux *rem, int fin, int fout, int mult)
652
{
653
        rem->video_info.framerate = 0;
654
        rem->audio_info.layer = -1;
655
        rem->fin = fin;
656
        rem->fout = fout;
657
        ring_init(&rem->vid_buffy, 40*BUFFYSIZE*mult);
658
        ring_init(&rem->aud_buffy, BUFFYSIZE*mult);
659
        init_ptsl(rem->vpts_list);
660
        init_ptsl(rem->apts_list);
661
        init_framel(rem->vframe_list);
662
        init_framel(rem->aframe_list);
663

    
664
        rem->vptsn     = 0;
665
        rem->aptsn     = 0;
666
        rem->vframen   = 0;
667
        rem->aframen   = 0;
668
        rem->vframe    = 0;
669
        rem->aframe    = 0;
670
        rem->vcframe   = 0;
671
        rem->acframe   = 0;
672
        rem->vpts      = 0;
673
        rem->vdts      = 0;
674
        rem->apts_off  = 0;
675
        rem->vpts_off  = 0;
676
        rem->apts_delay= 0;
677
        rem->vpts_delay= 0;
678
        rem->dts_delay = 0;
679
        rem->apts      = 0;
680
        rem->vpes      = 0;
681
        rem->apes      = 0;
682
        rem->vpts_old  = 0;
683
        rem->apts_old  = 0;
684
        rem->SCR       = 0;
685
        rem->vwrite    = 0;
686
        rem->awrite    = 0;
687
        rem->vread     = 0;
688
        rem->aread     = 0;
689
        rem->group     = 0;
690
        rem->groupframe= 0;
691
        rem->pack_size = 0;
692
        rem->muxr      = 0;
693
        rem->time_off  = 0;
694
}
695

    
696
uint32_t bytes2pts(int bytes, int rate)
697
{
698
        if (bytes < 0xFFFFFFFFUL/720000UL)
699
                return (uint32_t)(bytes*720000UL/rate);
700
        else
701
                return (uint32_t)(bytes/rate*720000UL);
702
}
703

    
704
long pts2bytes( uint32_t pts, int rate)
705
{
706
        if (pts < 0xEFFFFFFFUL/rate)
707
                return (pts*rate/720000);
708
        else 
709
                return (pts* (rate/720000));
710
}
711

    
712
int write_audio_pes( Remux *rem, uint8_t *buf, int *alength)
713
{
714
        int add;
715
        int pos = 0;
716
        int p   = 0;
717
        uint32_t pts = 0;
718
        int stuff = 0;
719
        int length = *alength;
720

    
721
        if (!length) return 0;
722
        p = PS_HEADER_L1+PES_H_MIN;
723

    
724
        if (rem->apts_old != rem->apts){
725
                pts = (uint32_t)((u64)rem->apts + rem->apts_delay - rem->apts_off);
726
                p += 5;
727
        }
728
        if ( length+p >= rem->pack_size){
729
                length = rem->pack_size;
730
        } else {
731
                if (rem->pack_size-length-p <= PES_MIN){
732
                        stuff = rem->pack_size - length;
733
                        length = rem->pack_size;
734
                } else 
735
                        length = length+p;
736
        }
737
        pos = write_ps_header(buf,rem->SCR,rem->muxr, 1, 0, 0, 1, 1, 1, 
738
                              0, 0, 0, 0, 0, 0);
739

    
740
        pos += write_pes_header( 0xC0, length-pos, pts, buf+pos, stuff);
741
        add = aring_read( rem, buf+pos, length-pos);
742
        *alength = add;
743
        if (add < 0) return -1;
744
        pos += add;
745
        rem->apts_old = rem->apts;
746
        rem->apts = rem->apts_list[0].PTS;
747

    
748
        if (pos+PES_MIN < rem->pack_size){
749
                pos += write_pes_header( PADDING_STREAM, rem->pack_size-pos, 0,
750
                                         buf+pos, 0);
751
                pos = rem->pack_size;
752
        }                
753
        if (pos != rem->pack_size) {
754
                fprintf(stderr,"apos: %d\n",pos);
755
                exit(1);
756
        }
757

    
758
        return pos;
759
}
760

    
761
int write_video_pes( Remux *rem, uint8_t *buf, int *vlength)
762
{
763
        int add;
764
        int pos = 0;
765
        int p   = 0;
766
        uint32_t pts = 0;
767
        uint32_t dts = 0;
768
        int stuff = 0;
769
        int length = *vlength;
770
        long diff = 0;
771

    
772
        if (! length) return 0;
773
        p = PS_HEADER_L1+PES_H_MIN;
774

    
775
        if (rem->vpts_old != rem->vpts){
776
                pts = (uint32_t)((u64)rem->vpts + rem->vpts_delay - rem->vpts_off);
777
                p += 5;
778
        }
779
        if ( length+p >= rem->pack_size){
780
                length = rem->pack_size;
781
        } else {
782
                if (rem->pack_size - length - p <= PES_MIN){
783
                        stuff = rem->pack_size - length;
784
                        length = rem->pack_size;
785
                } else 
786
                        length = length+p;
787
        }
788

    
789
        pos = write_ps_header(buf,rem->SCR,rem->muxr, 1, 0, 0, 1, 1, 1, 
790
                              0, 0, 0, 0, 0, 0);
791

    
792
        pos += write_pes_header( 0xE0, length-pos, pts, buf+pos, stuff);
793
        add = vring_read( rem, buf+pos, length-pos);
794
        *vlength = add;
795
        if (add < 0) return -1;
796
        pos += add;
797
        rem->vpts_old = rem->vpts;
798
        dts = rem->vdts;
799
        rem->vpts = rem->vpts_list[0].PTS;
800
        rem->vdts = rem->vpts_list[0].dts;
801
        if ( diff > 0) rem->SCR += diff;
802
        if (pos+PES_MIN < rem->pack_size){
803
                //  fprintf(stderr,"vstuffing: %d   \n",rem->pack_size-pos);
804
                pos += write_pes_header( PADDING_STREAM, rem->pack_size-pos, 0,
805
                                         buf+pos, 0);
806
                pos = rem->pack_size;
807
        }                
808
        return pos;
809
}
810

    
811
void print_info( Remux *rem , int ret)
812
{
813
        int newtime = 0;
814
        static int time = 0;
815
        int i = 0;
816

    
817
        while(! newtime && i < rem->vframen) {
818
                if( (newtime = rem->vframe_list[i].time)) break;
819
                i++;
820
        }
821
        if (newtime) time = newtime;
822
        
823
        fprintf(stderr,"SCR:");
824
        printpts(rem->SCR);
825
        fprintf(stderr," VDTS:");
826
        printpts((uint32_t)((u64)rem->vdts - rem->vpts_off + rem->vpts_delay));
827
        fprintf(stderr," APTS:");
828
        printpts((uint32_t)((u64)rem->apts - rem->apts_off + rem->apts_delay));
829
        fprintf(stderr," TIME:%2d:", time/3600);
830
        fprintf(stderr,"%02d:", (time%3600)/60);
831
        fprintf(stderr,"%02d", (time%3600)%60);
832
        if (ret) fprintf(stderr,"\n");
833
        else fprintf(stderr,"\r");
834
}
835

    
836
void remux(int fin, int fout, int pack_size, int mult)
837
{
838
        Remux rem;
839
        long ptsdiff;
840
        uint8_t buf[MAX_PACK_L];
841
        long pos = 0;
842
        int r = 0;
843
        int i, r1, r2;
844
        long packets = 0;
845
        uint8_t mpeg_end[4] = { 0x00, 0x00, 0x01, 0xB9 };
846
        uint32_t SCR_inc = 0;
847
        int data_size;
848
        long vbuf, abuf;
849
        long vbuf_max, abuf_max;
850
        PTS_List abufl[MAX_PTS];
851
        PTS_List vbufl[MAX_PTS];
852
        int abufn = 0;
853
        int vbufn = 0;
854
        u64 pts_d = 0;
855
        int ok_audio; 
856
        int ok_video; 
857
        uint32_t apos = 0;
858
        uint32_t vpos = 0;
859
        int vpack_size = 0;
860
        int apack_size = 0;
861

    
862
        init_ptsl(abufl);
863
        init_ptsl(vbufl);
864

    
865
        init_remux(&rem, fin, fout, mult);
866
        rem.pack_size = pack_size;
867
        data_size = pack_size - MAX_H_SIZE;
868
        fprintf(stderr,"pack_size: %d header_size: %d data size: %d\n",
869
                pack_size, MAX_H_SIZE, data_size);
870
        refill_buffy(&rem);
871
        fprintf(stderr,"Package size: %d\n",pack_size);
872
        
873
        if ( get_video_info(&rem) < 0 ){
874
                fprintf(stderr,"ERROR: Can't find valid video stream\n");
875
                exit(1);
876
        }
877

    
878
        i = 0;
879
        while(! rem.time_off && i < rem.vframen) {
880
                if( (rem.time_off = rem.vframe_list[i].time)) break;
881
                i++;
882
        }
883

    
884
        if ( get_audio_info(&rem) < 0 ){
885
                fprintf(stderr,"ERROR: Can't find valid audio stream\n");
886
                exit(1);
887
        }
888
        
889
        rem.vpts = rem.vpts_list[0].PTS;
890
        rem.vdts = rem.vpts;
891
        rem.vpts_off = rem.vpts;
892
        fprintf(stderr,"Video start PTS = %fs \n",rem.vpts_off/90000.);
893
        rem.apts = rem.apts_list[0].PTS;
894
        rem.apts_off = rem.apts;
895
        ptsdiff = rem.vpts - rem.apts;
896
        if (ptsdiff > 0) rem.vpts_off -= ptsdiff;
897
        else rem.apts_off -= -ptsdiff;
898
        fprintf(stderr,"Audio start PTS = %fs\n",rem.apts_off/90000.);
899
        fprintf(stderr,"Difference Video - Audio = %fs\n",ptsdiff/90000.);
900
        fprintf(stderr,"Time offset = %ds\n",rem.time_off);
901

    
902
        rem.muxr = (rem.video_info.bit_rate + 
903
                    rem.audio_info.bit_rate)/400;
904
        fprintf(stderr,"MUXRATE: %.2f Mb/sec\n",rem.muxr/2500.);
905
        SCR_inc = 1800 * pack_size / rem.muxr;
906
        
907
        r = 0;
908
        while ( rem.vptsn < 2 && !r) r = refill_buffy(&rem);
909
        r = 0;
910
        while ( rem.aptsn < 2 && !r) r = refill_buffy(&rem);
911

    
912
        //rem.vpts_delay =  (uint32_t)(2*90000ULL* (u64)pack_size/rem.muxr);
913
        rem.vpts_delay = rem.dts_delay;
914
        rem.apts_delay = rem.vpts_delay;
915

    
916
        vbuf_max = 29440;
917
        abuf_max = 4096;
918
        vbuf = 0;
919
        abuf = 0;
920
        pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, 
921
                              0xC0, 0, 32, 0xE0, 1, 230);
922
        pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0, buf+pos,0);
923
        pos = rem.pack_size;
924
        write( fout, buf, pos);
925

    
926
        apos = rem.aread;
927
        vpos = rem.vread;
928
        print_info( &rem, 1 );
929

    
930
        while( ring_rest(&rem.aud_buffy) && ring_rest(&rem.vid_buffy) ){
931
                uint32_t next_apts;
932
                uint32_t next_vdts;
933
                int asize, vsize;
934

    
935
                r1 = 0;
936
                r2 = 0;
937
                while ( rem.aframen < 2 && !r1) 
938
                        r1 = refill_buffy(&rem);
939
                while ( rem.vframen < 2 && !r2) 
940
                        r2 = refill_buffy(&rem);
941
                if (r1 && r2) break;
942

    
943
                if ( !r1 && apos <= rem.aread)
944
                        apos = rem.aframe_list[1].pos;
945
                if ( !r2 && vpos <= rem.vread)
946
                        vpos = rem.vframe_list[1].pos;
947
                apack_size = apos - rem.aread; 
948
                vpack_size = vpos - rem.vread; 
949
                
950

    
951
                next_vdts = (uint32_t)((u64)rem.vdts + rem.vpts_delay 
952
                                  - rem.vpts_off) ;
953
                ok_video = ( rem.SCR < next_vdts);
954

    
955
                next_apts = (uint32_t)((u64)rem.apts + rem.apts_delay 
956
                                  - rem.apts_off) ;
957
                ok_audio = ( rem.SCR  < next_apts);
958

    
959
                asize = (apack_size > data_size ? data_size: apack_size);
960
                vsize = (vpack_size > data_size ? data_size: vpack_size);
961

    
962
                fprintf(stderr,"vframen: %d  aframen: %d  v_ok: %d  a_ok: %d  v_buf: %d  a_buf: %d vpacks: %d  apacks: %d\n",rem.vframen,rem.aframen, ok_video, ok_audio, (int)vbuf,(int)abuf,vsize, asize);
963
                
964

    
965
                if( vbuf+vsize  < vbuf_max && vsize && ok_audio ){
966
                        fprintf(stderr,"1 ");
967
                        pos = write_video_pes( &rem, buf, &vpack_size);
968
                        write( fout, buf, pos);
969
                        vbuf += vpack_size;
970
                        vbufn = add_pts( vbufl, rem.vdts, vpack_size, 
971
                                         0, vbufn, 0);
972
                        packets++;
973
                } else if ( abuf+asize < abuf_max && asize &&
974
                            ok_video  ){
975
                        fprintf(stderr,"2 ");
976
                        pos = write_audio_pes( &rem, buf, &apack_size);
977
                        write( fout, buf, pos);
978
                        abuf += apack_size;
979
                        abufn = add_pts( abufl, rem.apts, apack_size, 
980
                                         0, abufn, 0);
981
                        packets++;
982
                } else if ( abuf+asize < abuf_max && asize &&
983
                            !ok_audio){
984
                        fprintf(stderr,"3 ");
985
                        pos = write_audio_pes( &rem, buf, &apack_size);
986
                        write( fout, buf, pos);
987
                        abuf += apack_size;
988
                        abufn = add_pts( abufl, rem.apts, apack_size, 
989
                                         0, abufn, 0);
990
                        packets++;
991
                } else if (vbuf+vsize  < vbuf_max && vsize &&
992
                           !ok_video){
993
                        fprintf(stderr,"4 ");
994
                        pos = write_video_pes( &rem, buf, &vpack_size);
995
                        write( fout, buf, pos);
996
                        vbuf += vpack_size;
997
                        vbufn = add_pts( vbufl, rem.vdts, vpack_size, 
998
                                         0, vbufn, 0);
999
                        packets++;
1000
                } else {
1001
                fprintf(stderr,"5 ");
1002
                        pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 
1003
                                              1, 1, 1, 0, 0, 0, 0, 0, 0);
1004

    
1005
                        pos += write_pes_header( PADDING_STREAM, pack_size-pos,
1006
                                                 0, buf+pos, 0);
1007
                        write( fout, buf, pos);
1008
                }
1009

    
1010

    
1011
                //fprintf(stderr,"vbufn: %d  abufn: %d  ", vbufn,abufn);
1012
                //fprintf(stderr,"vbuf: %5d  abuf: %4d\n", vbuf,abuf);
1013

    
1014
                if (rem.SCR > rem.vdts+rem.vpts_off -rem.vpts_delay) 
1015
                        rem.SCR = rem.vdts-rem.vpts_off;
1016
                rem.SCR = (uint32_t)((u64) rem.SCR + SCR_inc);
1017

    
1018
                if ( rem.apts_off + rem.SCR < rem.apts_delay ) pts_d = 0;
1019
                else pts_d = (u64) rem.SCR + rem.apts_off - rem.apts_delay;
1020
                abuf -= del_ptss( abufl, (uint32_t) pts_d, &abufn);
1021

    
1022
                if ( rem.vpts_off + rem.SCR < rem.vpts_delay ) pts_d = 0;
1023
                else pts_d = (u64) rem.SCR + rem.vpts_off - rem.vpts_delay;
1024
                vbuf -= del_ptss( vbufl, (uint32_t) pts_d, &vbufn);
1025

    
1026
                print_info( &rem, 1);
1027
                //fprintf(stderr,"vbufn: %d  abufn: %d  ", vbufn,abufn);
1028
                //fprintf(stderr,"vbuf: %5d  abuf: %4d\n\n", vbuf,abuf);
1029

    
1030

    
1031
        }
1032
        pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, 
1033
                              0, 0, 0, 0, 0, 0);
1034

    
1035
        pos += write_pes_header( PADDING_STREAM, pack_size-pos-4, 0, 
1036
                                 buf+pos, 0);
1037
        pos = rem.pack_size-4;
1038
        write( fout, buf, pos);
1039

    
1040
        write( fout, mpeg_end, 4);
1041
        fprintf(stderr,"\ndone\n");
1042
}
1043

    
1044

    
1045
typedef 
1046
struct pes_buffer_s{
1047
        ringbuffy   pes_buffy;
1048
        uint8_t     type;
1049
        PTS_List    pts_list[MAX_PTS];
1050
        FRAME_List  frame_list[MAX_FRAME];
1051
        int         pes_size;
1052
        uint64_t    written;
1053
        uint64_t    read;
1054
} PESBuffer;
1055

    
1056

    
1057
void init_PESBuffer(PESBuffer *pbuf, int pes_size, int buf_size, uint8_t type)
1058
{
1059
        init_framel( pbuf->frame_list);
1060
        init_ptsl( pbuf->pts_list);
1061
        ring_init( &pbuf->pes_buffy, buf_size);
1062
        pbuf->pes_size = pes_size;
1063
        pbuf->type = type; 
1064
        pbuf->written = 0;
1065
        pbuf->read = 0;
1066
}
1067
        
1068

    
1069
#define MAX_PBUF 4
1070

    
1071
typedef
1072
struct remux_s{
1073
        PESBuffer pbuf_list[MAX_PBUF];
1074
        int num_pbuf;
1075
} REMUX;
1076

    
1077

    
1078
void init_REMUX(REMUX *rem)
1079
{
1080
        rem->num_pbuf = 0;
1081
}
1082

    
1083

    
1084

    
1085
#define REPACK      2048 
1086
#define ABUF_SIZE   REPACK*1024
1087
#define VBUF_SIZE   REPACK*10240
1088

    
1089
void remux_main(uint8_t *buf, int count, p2p *p)
1090
{
1091
        int i, b;
1092
        int bufsize = 0;
1093
        PESBuffer *pbuf;
1094
        REMUX *rem = (REMUX *) p->data;
1095
        uint8_t type = buf[3];
1096
        int *npbuf = &(rem->num_pbuf);
1097

    
1098
        switch ( type ){
1099
        case PRIVATE_STREAM1:
1100
                bufsize = ABUF_SIZE;
1101
        case VIDEO_STREAM_S ... VIDEO_STREAM_E:
1102
                if (!bufsize) bufsize = VBUF_SIZE;
1103
        case AUDIO_STREAM_S ... AUDIO_STREAM_E:
1104
                if (!bufsize) bufsize = ABUF_SIZE;
1105
                b = -1;
1106
                for ( i = 0; i < *npbuf; i++){
1107
                        if ( type == rem->pbuf_list[i].type ){
1108
                                b = i;
1109
                                break;
1110
                        }
1111
                }
1112
                if (b < 0){
1113
                        if ( *npbuf < MAX_PBUF ){
1114
                                init_PESBuffer(&rem->pbuf_list[*npbuf], 
1115
                                               p->repack+6, bufsize, type);
1116
                                b = *npbuf;
1117
                                (*npbuf)++;
1118
                        } else {
1119
                                fprintf(stderr,"Not enough PES buffers\n");
1120
                                exit(1);
1121
                        }
1122
                }
1123
                break;
1124
        default:
1125
                return;
1126
        }
1127
        
1128
        pbuf = &(rem->pbuf_list[b]);
1129
        if (ring_write(&(pbuf->pes_buffy),(char *)buf,count) != count){
1130
                fprintf(stderr,"buffer overflow type 0x%2x\n",type);
1131
                exit(1);
1132
        } else {
1133
                pbuf->written += count;
1134
                if ((p->flag2 & PTS_DTS_FLAGS)){
1135
                        uint32_t PTS = ntohl(trans_pts_dts(p->pts));
1136
                        add_pts(pbuf->pts_list, PTS, pbuf->written, 
1137
                                pbuf->written, 0, 0);
1138
                }
1139
                p->flag2 = 0;
1140
        }
1141

    
1142
}
1143

    
1144
void output_mux(p2p *p) 
1145
{
1146
        int i, filling;
1147
        PESBuffer *pbuf;
1148
        ringbuffy   *pes_buffy;        
1149
        REMUX *rem = (REMUX *) p->data;
1150
        int repack = p->repack;
1151
        int npbuf = rem->num_pbuf;
1152

    
1153
        for ( i = 0; i < npbuf; i++){
1154
                pbuf = &(rem->pbuf_list[i]);
1155
                pes_buffy = &pbuf->pes_buffy;
1156
                filling = pes_buffy->size - ring_rest(pes_buffy);
1157
                if (filling/(2 *repack)){
1158
                        pbuf->read += ring_read_file(pes_buffy, p->fd1, 
1159
                                                     (filling/repack)*repack);
1160
                }
1161
        }
1162
}
1163

    
1164

    
1165

    
1166
#define SIZE 32768
1167

    
1168
void remux2(int fdin, int fdout)
1169
{
1170
        p2p p;
1171
        int count = 1;
1172
        uint8_t buf[SIZE];
1173
        uint64_t length = 0;
1174
        uint64_t l = 0;
1175
        int verb = 0;
1176
        REMUX rem;
1177
        
1178
        init_p2p(&p, remux_main, REPACK);
1179
        p.fd1 = fdout;
1180
        p.data = (void *) &rem;
1181
        
1182

    
1183
        if (fdin != STDIN_FILENO) verb = 1; 
1184

    
1185
        if (verb) {
1186
                length = lseek(fdin, 0, SEEK_END);
1187
                lseek(fdin,0,SEEK_SET);
1188
        }
1189

    
1190
        while (count > 0){
1191
                count = read(fdin,buf,SIZE);
1192
                l += count;
1193
                if (verb)
1194
                        fprintf(stderr,"Writing  %2.2f %%\r",
1195
                                100.*l/length);
1196

    
1197
                get_pes(buf,count,&p,pes_repack);
1198
                output_mux(&p);
1199
        }
1200
                
1201
}