]> git.vomp.tv Git - vompserver.git/blob - libdvbmpeg/remux.c
Initial import
[vompserver.git] / libdvbmpeg / remux.c
1 /*
2  *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
3  *
4  * Copyright (C) 2000, 2001 Marcus Metzler 
5  *            for convergence integrated media GmbH
6  * Copyright (C) 2002 Marcus Metzler 
7  * 
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  * 
13
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
24  * 
25
26  * The author can be reached at mocm@metzlerbros.de, 
27  */
28
29 #include "remux.h"
30
31 unsigned int bitrates[3][16] =
32 {{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
33  {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
34  {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
35
36 uint32_t freq[4] = {441, 480, 320, 0};
37 static uint32_t samples[4] = { 384, 1152, 0, 0};
38 char *frames[3] = {"I-Frame","P-Frame","B-Frame"};
39
40
41 void copy_ptslm(PTS_List *a, PTS_List *b)
42 {
43         a->pos  = b->pos;
44         a->PTS  = b->PTS;
45         a->dts  = b->dts;
46         a->spos = b->spos;
47 }
48
49 void clear_ptslm(PTS_List *a)
50 {
51         a->pos  = 0;
52         a->PTS  = 0;
53         a->dts  = 0;
54         a->spos = 0;    
55 }
56
57 void init_ptsl(PTS_List *ptsl)
58 {
59         int i;
60         for (i=0;i< MAX_PTS;i++){
61                 clear_ptslm(&ptsl[i]);
62         }
63 }
64
65 int del_pts(PTS_List *ptsl, int pos, int nr)
66 {
67         int i;
68         int del = 0;
69
70         for( i = 0; i < nr-1; i++){
71                 if(pos > ptsl[i].pos && pos >= ptsl[i+1].pos) del++;
72         }
73
74         if(del)
75                 for( i = 0; i < nr-del; i++){
76                         copy_ptslm(&ptsl[i], &ptsl[i+del]);
77                 }
78
79         return nr-del;
80 }
81
82 int del_ptss(PTS_List *ptsl, int pts, int *nb)
83 {
84         int i;
85         int del = 0;
86         int sum = 0;
87         int nr = *nb;
88
89         for( i = 0; i < nr; i++){
90                 if(pts > ptsl[i].PTS){
91                         del++;
92                         sum += ptsl[i].pos;
93                 }
94         }
95
96         if(del)
97                 for( i = 0; i < nr-del; i++){
98                         copy_ptslm(&ptsl[i], &ptsl[i+del]);
99                 }
100
101         *nb = nr-del;
102         return sum;
103 }
104
105 int add_pts(PTS_List *ptsl, uint32_t pts, int pos, int spos, int nr, uint32_t dts)
106 {
107         int i;
108
109         for ( i=0;i < nr; i++) if (spos &&  ptsl[i].pos == pos) return nr;
110         if (nr == MAX_PTS) {
111                 nr = del_pts(ptsl, ptsl[1].pos+1, nr);
112         } else nr++;
113         i = nr-1;
114         
115         ptsl[i].pos  = pos;
116         ptsl[i].spos = spos;
117         ptsl[i].PTS  = pts;
118         ptsl[i].dts  = dts;
119         return nr;
120 }
121
122 void add_vpts(Remux *rem, uint8_t *pts)
123 {
124         uint32_t PTS = trans_pts_dts(pts);
125         rem->vptsn = add_pts(rem->vpts_list, PTS, rem->vwrite, rem->awrite,
126                              rem->vptsn, PTS);
127 }
128
129 void add_apts(Remux *rem, uint8_t *pts)
130 {
131         uint32_t PTS = trans_pts_dts(pts);
132         rem->aptsn = add_pts(rem->apts_list, PTS, rem->awrite, rem->vwrite,
133                              rem->aptsn, PTS);
134 }
135
136 void del_vpts(Remux *rem)
137 {
138         rem->vptsn = del_pts(rem->vpts_list, rem->vread, rem->vptsn);
139 }
140
141 void del_apts(Remux *rem)
142 {
143         rem->aptsn = del_pts(rem->apts_list, rem->aread, rem->aptsn);
144 }
145
146
147 void copy_framelm(FRAME_List *a, FRAME_List *b)
148 {
149         a->type  = b->type;
150         a->pos   = b->pos;
151         a->FRAME = b->FRAME;
152         a->time  = b->time;
153         a->pts   = b->pts;
154         a->dts   = b->dts;
155 }
156
157 void clear_framelm(FRAME_List *a)
158 {
159         a->type  = 0;
160         a->pos   = 0;
161         a->FRAME = 0;
162         a->time  = 0; 
163         a->pts   = 0; 
164         a->dts   = 0; 
165 }
166
167 void init_framel(FRAME_List *framel)
168 {
169         int i;
170         for (i=0;i< MAX_FRAME;i++){
171                 clear_framelm(&framel[i]);
172         }
173 }
174
175 int del_frame(FRAME_List *framel, int pos, int nr)
176 {
177         int i;
178         int del = 0;
179
180         for( i = 0; i < nr-1; i++){
181                 if(pos > framel[i].pos && pos >= framel[i+1].pos) del++;
182         }
183
184         if(del)
185                 for( i = 0; i < nr-del; i++){
186                         copy_framelm(&framel[i], &framel[i+del]);
187                 }
188
189         return nr-del;
190 }
191
192 int add_frame(FRAME_List *framel, uint32_t frame, int pos, int type, int nr, 
193               uint32_t time, uint32_t pts, uint32_t dts)
194 {
195         int i;
196
197         if (nr == MAX_FRAME) {
198                 nr = del_frame(framel, framel[1].pos+1, nr);
199         } else nr++;
200         i = nr-1;
201         
202         framel[i].type  = type;
203         framel[i].pos   = pos;
204         framel[i].FRAME = frame;
205         framel[i].time  = time;
206         framel[i].pts   = pts;
207         framel[i].dts   = dts;
208         return nr;
209 }
210
211 void add_vframe(Remux *rem, uint32_t frame, long int pos, int type, int time, 
212                 uint32_t pts, uint32_t dts)
213 {
214         rem->vframen = add_frame(rem->vframe_list, frame, pos, type,
215                                  rem->vframen, time, pts, dts);
216 }
217
218 void add_aframe(Remux *rem, uint32_t frame, long int pos, uint32_t pts)
219 {
220         rem->aframen = add_frame(rem->aframe_list, frame, pos, 0, 
221                                  rem->aframen, 0, pts, pts);
222 }
223
224 void del_vframe(Remux *rem)
225 {
226         rem->vframen = del_frame(rem->vframe_list, rem->vread, rem->vframen);
227 }
228
229 void del_aframe(Remux *rem)
230 {
231         rem->aframen = del_frame(rem->aframe_list, rem->aread, rem->aframen);
232 }
233
234
235 void printpts(uint32_t pts)
236 {
237         fprintf(stderr,"%2d:%02d:%02d.%03d",
238                 (int)(pts/90000.)/3600,
239                 ((int)(pts/90000.)%3600)/60,
240                 ((int)(pts/90000.)%3600)%60,
241                 (((int)(pts/90.)%3600000)%60000)%1000
242                 );
243 }
244
245
246 void find_vframes( Remux *rem, uint8_t *buf, int l)
247 {
248         int c = 0;
249         int type;
250         uint32_t time = 0;
251         int hour;
252         int min;
253         int sec;
254         uint64_t pts=0;
255         uint64_t dts=0;
256         uint32_t tempref = 0;
257
258         while ( c < l - 6){
259                 if (buf[c] == 0x00 && 
260                     buf[c+1] == 0x00 &&
261                     buf[c+2] == 0x01 && 
262                     buf[c+3] == 0xB8) {
263                         c += 4;
264                         hour = (int)((buf[c]>>2)& 0x1F);
265                         min  = (int)(((buf[c]<<4)& 0x30)| 
266                                      ((buf[c+1]>>4)& 0x0F));
267                         sec  = (int)(((buf[c+1]<<3)& 0x38)|
268                                       ((buf[c+2]>>5)& 0x07));
269   
270                         time = 3600*hour + 60*min + sec;
271                         if ( rem->time_off){
272                                 time = (uint32_t)((uint64_t)time - rem->time_off);
273                                 hour = time/3600;
274                                 min  = (time%3600)/60;
275                                 sec  = (time%3600)%60;
276                                 /*
277                                 buf[c]   |= (hour & 0x1F) << 2;
278                                 buf[c]   |= (min & 0x30) >> 4;
279                                 buf[c+1] |= (min & 0x0F) << 4;
280                                 buf[c+1] |= (sec & 0x38) >> 3;
281                                 buf[c+2] |= (sec & 0x07) >> 5;*/
282                         }
283                         rem->group++;
284                         rem->groupframe = 0;
285                 }
286                 if ( buf[c] == 0x00 && 
287                      buf[c+1] == 0x00 &&
288                      buf[c+2] == 0x01 && 
289                      buf[c+3] == 0x00) {
290                         c += 4;
291                         tempref = (buf[c+1]>>6) & 0x03;
292                         tempref |= buf[c] << 2;
293                         
294                         type = ((buf[c+1]&0x38) >>3);
295                         if ( rem->video_info.framerate){
296                                 pts = ((uint64_t)rem->vframe + tempref + 1 
297                                         - rem->groupframe ) * 90000ULL
298                                             /rem->video_info.framerate 
299                                         + rem->vpts_off;
300                                 dts = (uint64_t)rem->vframe * 90000ULL/
301                                         rem->video_info.framerate 
302                                         + rem->vpts_off;
303                         
304
305 fprintf(stderr,"MYPTS:");
306 printpts((uint32_t)pts-rem->vpts_off);
307  fprintf(stderr,"   REALPTS:");
308  printpts(rem->vpts_list[rem->vptsn-1].PTS-rem->vpts_off);
309  fprintf(stderr,"   DIFF:");
310  printpts(pts-(uint64_t)rem->vpts_list[rem->vptsn-1].PTS);
311 // fprintf(stderr,"   DIST: %4d",-rem->vpts_list[rem->vptsn-1].pos+(rem->vwrite+c-4));
312  //fprintf(stderr,"   ERR: %3f",(double)(-rem->vpts_list[rem->vptsn-1].PTS+pts)/(rem->vframe+1));
313  fprintf(stderr,"\r");
314
315                                 
316                                 
317                                 rem->vptsn = add_pts(rem->vpts_list,(uint32_t)pts
318                                                      ,rem->vwrite+c-4,
319                                                      rem->awrite,
320                                                      rem->vptsn,
321                                                      (uint32_t)dts);
322
323                                 
324                                 
325                         }
326                         rem->vframe++;
327                         rem->groupframe++;
328                         add_vframe( rem, rem->vframe, rem->vwrite+c, type, 
329                                     time, pts, dts);
330                 } else c++;
331         }
332 }
333
334 void find_aframes( Remux *rem, uint8_t *buf, int l)
335 {
336         int c = 0;
337         uint64_t pts = 0;
338         int sam;
339         uint32_t fr;
340
341
342         while ( c < l - 2){
343                 if ( buf[c] == 0xFF && 
344                      (buf[c+1] & 0xF8) == 0xF8) {
345                         c += 2;
346                         if ( rem->audio_info.layer >= 0){
347                                 sam = samples[3-rem->audio_info.layer];
348                                 fr = freq[rem->audio_info.frequency] ;
349                 
350                           pts = ( (uint64_t)rem->aframe * sam * 900ULL)/fr
351                                   + rem->apts_off;
352                                 
353
354 fprintf(stderr,"MYPTS:");
355 printpts((uint32_t)pts-rem->apts_off);
356  fprintf(stderr," REALPTS:");
357  printpts(rem->apts_list[rem->aptsn-1].PTS-rem->apts_off);
358  fprintf(stderr," DIFF:");
359  printpts((uint32_t)((uint64_t)rem->apts_list[rem->aptsn-1].PTS-pts));
360 // fprintf(stderr," DIST: %4d",-rem->apts_list[rem->aptsn-1].pos+(rem->awrite+c-2));
361  fprintf(stderr,"\r");
362
363                           rem->aptsn = add_pts(rem->apts_list,(uint32_t)pts
364                                              ,rem->awrite+c-2,
365                                              rem->vwrite,
366                                              rem->aptsn,
367                                              (uint32_t)pts);
368                 }
369
370                         rem->aframe++;
371                         add_aframe( rem, rem->aframe, rem->awrite+c, pts);
372                         
373                 } else c++;
374         }
375 }
376
377 int refill_buffy(Remux *rem)
378 {
379         pes_packet pes;
380         int count = 0;
381         int acount, vcount;
382         ringbuffy *vbuf = &rem->vid_buffy;
383         ringbuffy *abuf = &rem->aud_buffy;
384         int fin = rem->fin;
385
386         acount = abuf->size-ring_rest(abuf);
387         vcount = vbuf->size-ring_rest(vbuf);
388         
389         
390         while ( acount > MAX_PLENGTH && vcount > MAX_PLENGTH && count < 10){
391                 int neof;
392                 count++;
393                 init_pes(&pes);
394                 if ((neof = read_pes(fin,&pes)) <= 0) return -1;
395                 switch(pes.stream_id){
396                 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
397                         rem->apes++;
398                         if( rem->audio_info.layer < 0 &&
399                             (pes.flags2 & PTS_DTS) )
400                                 add_apts(rem, pes.pts);
401                         find_aframes( rem, pes.pes_pckt_data, pes.length);
402                         ring_write(abuf,(char *)pes.pes_pckt_data,pes.length);
403                         rem->awrite += pes.length;
404                         break;
405                 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
406                         rem->vpes++;
407                         if( !rem->video_info.framerate &&
408                             (pes.flags2 & PTS_DTS) )
409                                 add_vpts(rem, pes.pts);
410
411                         find_vframes( rem, pes.pes_pckt_data, pes.length);
412
413                         ring_write(vbuf,(char *)pes.pes_pckt_data,pes.length);
414                         rem->vwrite += pes.length;
415                         break;
416                 }
417                 acount = abuf->size-ring_rest(abuf);
418                 vcount = vbuf->size-ring_rest(vbuf);
419                 kill_pes(&pes);
420         }
421         if (count < 10) return 0;
422         return 1;
423 }
424
425 int vring_read( Remux *rem, uint8_t *buf, int l)
426 {
427         int c = 0;
428         int r = 0;
429
430         if (ring_rest(&rem->vid_buffy) <= l)
431                 r = refill_buffy(rem);
432         if (r) return -1;
433
434         c = ring_read(&rem->vid_buffy, (char *) buf, l);
435         rem->vread += c;
436         del_vpts(rem);
437         del_vframe(rem);
438         return c;
439 }
440
441 int aring_read( Remux *rem, uint8_t *buf, int l)
442 {
443         int c = 0;
444         int r = 0;
445
446         if (ring_rest(&rem->aud_buffy) <= l)
447                 r = refill_buffy(rem);
448         if (r) return -1;
449         
450         c = ring_read(&rem->aud_buffy, (char *)buf, l);
451         rem->aread += c;
452         del_apts(rem);
453         del_aframe(rem);
454         return c;
455 }
456
457 int vring_peek( Remux *rem, uint8_t *buf, int l, long off)
458 {
459         int c = 0;
460         
461         if (ring_rest(&rem->vid_buffy) <= l)
462                 refill_buffy(rem);
463
464         c = ring_peek(&rem->vid_buffy, (char *) buf, l, off);
465         return c;
466 }
467
468 int aring_peek( Remux *rem, uint8_t *buf, int l, long off)
469 {
470         int c = 0;
471
472         if (ring_rest(&rem->aud_buffy) <= l)
473                 refill_buffy(rem);
474
475         c = ring_peek(&rem->aud_buffy, (char *)buf, l, off);
476         return c;
477 }
478
479
480 int get_video_info(Remux *rem)
481 {
482         uint8_t buf[12];
483         uint8_t *headr;
484         int found = 0;
485         int sw;
486         long off = 0;
487         int form = -1;
488         ringbuffy *vid_buffy = &rem->vid_buffy;
489         VideoInfo *vi = &rem->video_info;
490
491         while (found < 4 && ring_rest(vid_buffy)){
492                 uint8_t b[3];
493
494                 vring_peek( rem, b, 4, 0);
495                 if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
496                      && b[3] == 0xb3) found = 4;
497                 else {
498                         off++;
499                         vring_read( rem, b, 1);
500                 }
501         }
502         rem->vframe = rem->vframen-1;
503
504         if (! found) return -1;
505         buf[0] = 0x00; buf[1] = 0x00; buf[2] = 0x01; buf[3] = 0xb3;
506         headr = buf+4;
507         if(vring_peek(rem, buf, 12, 0) < 12) return -1;
508
509         vi->horizontal_size     = ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
510         vi->vertical_size       = ((headr[1] &0x0F) << 8) | (headr[2]);
511     
512         sw = (int)((headr[3]&0xF0) >> 4) ;
513
514         switch( sw ){
515         case 1:
516                 fprintf(stderr,"Videostream: ASPECT: 1:1");
517                 vi->aspect_ratio = 100;        
518                 break;
519         case 2:
520                 fprintf(stderr,"Videostream: ASPECT: 4:3");
521                 vi->aspect_ratio = 133;        
522                 break;
523         case 3:
524                 fprintf(stderr,"Videostream: ASPECT: 16:9");
525                 vi->aspect_ratio = 177;        
526                 break;
527         case 4:
528                 fprintf(stderr,"Videostream: ASPECT: 2.21:1");
529                 vi->aspect_ratio = 221;        
530                 break;
531
532         case 5 ... 15:
533                 fprintf(stderr,"Videostream: ASPECT: reserved");
534                 vi->aspect_ratio = 0;        
535                 break;
536
537         default:
538                 vi->aspect_ratio = 0;        
539                 return -1;
540         }
541
542         fprintf(stderr,"  Size = %dx%d",vi->horizontal_size,vi->vertical_size);
543
544         sw = (int)(headr[3]&0x0F);
545
546         switch ( sw ) {
547         case 1:
548                 fprintf(stderr,"  FRate: 23.976 fps");
549                 vi->framerate = 24000/1001.;
550                 form = -1;
551                 break;
552         case 2:
553                 fprintf(stderr,"  FRate: 24 fps");
554                 vi->framerate = 24;
555                 form = -1;
556                 break;
557         case 3:
558                 fprintf(stderr,"  FRate: 25 fps");
559                 vi->framerate = 25;
560                 form = VIDEO_MODE_PAL;
561                 break;
562         case 4:
563                 fprintf(stderr,"  FRate: 29.97 fps");
564                 vi->framerate = 30000/1001.;
565                 form = VIDEO_MODE_NTSC;
566                 break;
567         case 5:
568                 fprintf(stderr,"  FRate: 30 fps");
569                 vi->framerate = 30;
570                 form = VIDEO_MODE_NTSC;
571                 break;
572         case 6:
573                 fprintf(stderr,"  FRate: 50 fps");
574                 vi->framerate = 50;
575                 form = VIDEO_MODE_PAL;
576                 break;
577         case 7:
578                 fprintf(stderr,"  FRate: 60 fps");
579                 vi->framerate = 60;
580                 form = VIDEO_MODE_NTSC;
581                 break;
582         }
583
584         rem->dts_delay = (int)(7.0/vi->framerate/2.0*90000);
585
586         vi->bit_rate = 400*(((headr[4] << 10) & 0x0003FC00UL) 
587                             | ((headr[5] << 2) & 0x000003FCUL) | 
588                             (((headr[6] & 0xC0) >> 6) & 0x00000003UL));
589         
590         fprintf(stderr,"  BRate: %.2f Mbit/s",(vi->bit_rate)/1000000.);
591         
592         fprintf(stderr,"\n");
593         vi->video_format = form;
594
595         /*
596         marker_bit (&video_bs, 1);
597         vi->vbv_buffer_size     = getbits (&video_bs, 10);
598         vi->CSPF                = get1bit (&video_bs);
599         */
600         return form;
601 }
602
603
604 int get_audio_info( Remux *rem)
605 {
606         uint8_t *headr;
607         uint8_t buf[3];
608         long off = 0;
609         int found = 0;
610         ringbuffy *aud_buffy = &rem->aud_buffy;
611         AudioInfo *ai = &rem->audio_info;
612         
613         while(!ring_rest(aud_buffy) && !refill_buffy(rem));
614         while (found < 2 && ring_rest(aud_buffy)){
615                 uint8_t b[2];
616                 refill_buffy(rem);
617                 aring_peek( rem, b, 2, 0);
618
619                 if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
620                         found = 2;
621                 else {
622                         off++;
623                         aring_read( rem, b, 1);
624                 }
625         }       
626
627         if (!found) return -1;
628         rem->aframe = rem->aframen-1;
629         
630         if (aring_peek(rem, buf, 3, 0) < 1) return -1;
631         headr = buf+2;
632
633         ai->layer = (buf[1] & 0x06) >> 1;
634
635         fprintf(stderr,"Audiostream: Layer: %d", 4-ai->layer);
636
637
638         ai->bit_rate = bitrates[(3-ai->layer)][(headr[0] >> 4 )]*1000;
639
640         if (ai->bit_rate == 0)
641                 fprintf (stderr,"  Bit rate: free");
642         else if (ai->bit_rate == 0xf)
643                 fprintf (stderr,"  BRate: reserved");
644         else
645                 fprintf (stderr,"  BRate: %d kb/s", ai->bit_rate/1000);
646         
647
648         ai->frequency = (headr[0] & 0x0c ) >> 2;
649         if (ai->frequency == 3)
650                 fprintf (stderr, "  Freq: reserved\n");
651         else
652                 fprintf (stderr,"  Freq: %2.1f kHz\n", 
653                          freq[ai->frequency]/10.);
654
655         return 0;
656 }
657
658
659
660 void init_remux(Remux *rem, int fin, int fout, int mult)
661 {
662         rem->video_info.framerate = 0;
663         rem->audio_info.layer = -1;
664         rem->fin = fin;
665         rem->fout = fout;
666         ring_init(&rem->vid_buffy, 40*BUFFYSIZE*mult);
667         ring_init(&rem->aud_buffy, BUFFYSIZE*mult);
668         init_ptsl(rem->vpts_list);
669         init_ptsl(rem->apts_list);
670         init_framel(rem->vframe_list);
671         init_framel(rem->aframe_list);
672
673         rem->vptsn     = 0;
674         rem->aptsn     = 0;
675         rem->vframen   = 0;
676         rem->aframen   = 0;
677         rem->vframe    = 0;
678         rem->aframe    = 0;
679         rem->vcframe   = 0;
680         rem->acframe   = 0;
681         rem->vpts      = 0;
682         rem->vdts      = 0;
683         rem->apts_off  = 0;
684         rem->vpts_off  = 0;
685         rem->apts_delay= 0;
686         rem->vpts_delay= 0;
687         rem->dts_delay = 0;
688         rem->apts      = 0;
689         rem->vpes      = 0;
690         rem->apes      = 0;
691         rem->vpts_old  = 0;
692         rem->apts_old  = 0;
693         rem->SCR       = 0;
694         rem->vwrite    = 0;
695         rem->awrite    = 0;
696         rem->vread     = 0;
697         rem->aread     = 0;
698         rem->group     = 0;
699         rem->groupframe= 0;
700         rem->pack_size = 0;
701         rem->muxr      = 0;
702         rem->time_off  = 0;
703 }
704
705 uint32_t bytes2pts(int bytes, int rate)
706 {
707         if (bytes < 0xFFFFFFFFUL/720000UL)
708                 return (uint32_t)(bytes*720000UL/rate);
709         else
710                 return (uint32_t)(bytes/rate*720000UL);
711 }
712
713 long pts2bytes( uint32_t pts, int rate)
714 {
715         if (pts < 0xEFFFFFFFUL/rate)
716                 return (pts*rate/720000);
717         else 
718                 return (pts* (rate/720000));
719 }
720
721 int write_audio_pes( Remux *rem, uint8_t *buf, int *alength)
722 {
723         int add;
724         int pos = 0;
725         int p   = 0;
726         uint32_t pts = 0;
727         int stuff = 0;
728         int length = *alength;
729
730         if (!length) return 0;
731         p = PS_HEADER_L1+PES_H_MIN;
732
733         if (rem->apts_old != rem->apts){
734                 pts = (uint32_t)((uint64_t)rem->apts + rem->apts_delay - rem->apts_off);
735                 p += 5;
736         }
737         if ( length+p >= rem->pack_size){
738                 length = rem->pack_size;
739         } else {
740                 if (rem->pack_size-length-p <= PES_MIN){
741                         stuff = rem->pack_size - length;
742                         length = rem->pack_size;
743                 } else 
744                         length = length+p;
745         }
746         pos = write_ps_header(buf,rem->SCR,rem->muxr, 1, 0, 0, 1, 1, 1, 
747                               0, 0, 0, 0, 0, 0);
748
749         pos += write_pes_header( 0xC0, length-pos, pts, buf+pos, stuff);
750         add = aring_read( rem, buf+pos, length-pos);
751         *alength = add;
752         if (add < 0) return -1;
753         pos += add;
754         rem->apts_old = rem->apts;
755         rem->apts = rem->apts_list[0].PTS;
756
757         if (pos+PES_MIN < rem->pack_size){
758                 pos += write_pes_header( PADDING_STREAM, rem->pack_size-pos, 0,
759                                          buf+pos, 0);
760                 pos = rem->pack_size;
761         }               
762         if (pos != rem->pack_size) {
763                 fprintf(stderr,"apos: %d\n",pos);
764                 exit(1);
765         }
766
767         return pos;
768 }
769
770 int write_video_pes( Remux *rem, uint8_t *buf, int *vlength)
771 {
772         int add;
773         int pos = 0;
774         int p   = 0;
775         uint32_t pts = 0;
776         uint32_t dts = 0;
777         int stuff = 0;
778         int length = *vlength;
779         long diff = 0;
780
781         if (! length) return 0;
782         p = PS_HEADER_L1+PES_H_MIN;
783
784         if (rem->vpts_old != rem->vpts){
785                 pts = (uint32_t)((uint64_t)rem->vpts + rem->vpts_delay - rem->vpts_off);
786                 p += 5;
787         }
788         if ( length+p >= rem->pack_size){
789                 length = rem->pack_size;
790         } else {
791                 if (rem->pack_size - length - p <= PES_MIN){
792                         stuff = rem->pack_size - length;
793                         length = rem->pack_size;
794                 } else 
795                         length = length+p;
796         }
797
798         pos = write_ps_header(buf,rem->SCR,rem->muxr, 1, 0, 0, 1, 1, 1, 
799                               0, 0, 0, 0, 0, 0);
800
801         pos += write_pes_header( 0xE0, length-pos, pts, buf+pos, stuff);
802         add = vring_read( rem, buf+pos, length-pos);
803         *vlength = add;
804         if (add < 0) return -1;
805         pos += add;
806         rem->vpts_old = rem->vpts;
807         dts = rem->vdts;
808         rem->vpts = rem->vpts_list[0].PTS;
809         rem->vdts = rem->vpts_list[0].dts;
810         if ( diff > 0) rem->SCR += diff;
811         if (pos+PES_MIN < rem->pack_size){
812                 //  fprintf(stderr,"vstuffing: %d   \n",rem->pack_size-pos);
813                 pos += write_pes_header( PADDING_STREAM, rem->pack_size-pos, 0,
814                                          buf+pos, 0);
815                 pos = rem->pack_size;
816         }               
817         return pos;
818 }
819
820 void print_info( Remux *rem , int ret)
821 {
822         int newtime = 0;
823         static int time = 0;
824         int i = 0;
825
826         while(! newtime && i < rem->vframen) {
827                 if( (newtime = rem->vframe_list[i].time)) break;
828                 i++;
829         }
830         if (newtime) time = newtime;
831         
832         fprintf(stderr,"SCR:");
833         printpts(rem->SCR);
834         fprintf(stderr," VDTS:");
835         printpts((uint32_t)((uint64_t)rem->vdts - rem->vpts_off + rem->vpts_delay));
836         fprintf(stderr," APTS:");
837         printpts((uint32_t)((uint64_t)rem->apts - rem->apts_off + rem->apts_delay));
838         fprintf(stderr," TIME:%2d:", time/3600);
839         fprintf(stderr,"%02d:", (time%3600)/60);
840         fprintf(stderr,"%02d", (time%3600)%60);
841         if (ret) fprintf(stderr,"\n");
842         else fprintf(stderr,"\r");
843 }
844
845 void remux(int fin, int fout, int pack_size, int mult)
846 {
847         Remux rem;
848         long ptsdiff;
849         uint8_t buf[MAX_PACK_L];
850         long pos = 0;
851         int r = 0;
852         int i, r1, r2;
853         long packets = 0;
854         uint8_t mpeg_end[4] = { 0x00, 0x00, 0x01, 0xB9 };
855         uint32_t SCR_inc = 0;
856         int data_size;
857         long vbuf, abuf;
858         long vbuf_max, abuf_max;
859         PTS_List abufl[MAX_PTS];
860         PTS_List vbufl[MAX_PTS];
861         int abufn = 0;
862         int vbufn = 0;
863         uint64_t pts_d = 0;
864         int ok_audio; 
865         int ok_video; 
866         uint32_t apos = 0;
867         uint32_t vpos = 0;
868         int vpack_size = 0;
869         int apack_size = 0;
870
871         init_ptsl(abufl);
872         init_ptsl(vbufl);
873
874         if (mult < 0 || mult >1000){
875                 fprintf(stderr,"Multipler too large\n");
876                 exit(1);
877         }
878         init_remux(&rem, fin, fout, mult);
879         rem.pack_size = pack_size;
880         data_size = pack_size - MAX_H_SIZE;
881         fprintf(stderr,"pack_size: %d header_size: %d data size: %d\n",
882                 pack_size, MAX_H_SIZE, data_size);
883         refill_buffy(&rem);
884         fprintf(stderr,"Package size: %d\n",pack_size);
885         
886         if ( get_video_info(&rem) < 0 ){
887                 fprintf(stderr,"ERROR: Can't find valid video stream\n");
888                 exit(1);
889         }
890
891         i = 0;
892         while(! rem.time_off && i < rem.vframen) {
893                 if( (rem.time_off = rem.vframe_list[i].time)) break;
894                 i++;
895         }
896
897         if ( get_audio_info(&rem) < 0 ){
898                 fprintf(stderr,"ERROR: Can't find valid audio stream\n");
899                 exit(1);
900         }
901         
902         rem.vpts = rem.vpts_list[0].PTS;
903         rem.vdts = rem.vpts;
904         rem.vpts_off = rem.vpts;
905         fprintf(stderr,"Video start PTS = %fs \n",rem.vpts_off/90000.);
906         rem.apts = rem.apts_list[0].PTS;
907         rem.apts_off = rem.apts;
908         ptsdiff = rem.vpts - rem.apts;
909         if (ptsdiff > 0) rem.vpts_off -= ptsdiff;
910         else rem.apts_off -= -ptsdiff;
911         fprintf(stderr,"Audio start PTS = %fs\n",rem.apts_off/90000.);
912         fprintf(stderr,"Difference Video - Audio = %fs\n",ptsdiff/90000.);
913         fprintf(stderr,"Time offset = %ds\n",rem.time_off);
914
915         rem.muxr = (rem.video_info.bit_rate + 
916                     rem.audio_info.bit_rate)/400;
917         fprintf(stderr,"MUXRATE: %.2f Mb/sec\n",rem.muxr/2500.);
918         SCR_inc = 1800 * pack_size / rem.muxr;
919         
920         r = 0;
921         while ( rem.vptsn < 2 && !r) r = refill_buffy(&rem);
922         r = 0;
923         while ( rem.aptsn < 2 && !r) r = refill_buffy(&rem);
924
925         //rem.vpts_delay =  (uint32_t)(2*90000ULL* (uint64_t)pack_size/rem.muxr);
926         rem.vpts_delay = rem.dts_delay;
927         rem.apts_delay = rem.vpts_delay;
928
929         vbuf_max = 29440;
930         abuf_max = 4096;
931         vbuf = 0;
932         abuf = 0;
933         pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, 
934                               0xC0, 0, 32, 0xE0, 1, 230);
935         pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0, buf+pos,0);
936         pos = rem.pack_size;
937         write( fout, buf, pos);
938
939         apos = rem.aread;
940         vpos = rem.vread;
941         print_info( &rem, 1 );
942
943         while( ring_rest(&rem.aud_buffy) && ring_rest(&rem.vid_buffy) ){
944                 uint32_t next_apts;
945                 uint32_t next_vdts;
946                 int asize, vsize;
947
948                 r1 = 0;
949                 r2 = 0;
950                 while ( rem.aframen < 2 && !r1) 
951                         r1 = refill_buffy(&rem);
952                 while ( rem.vframen < 2 && !r2) 
953                         r2 = refill_buffy(&rem);
954                 if (r1 && r2) break;
955
956                 if ( !r1 && apos <= rem.aread)
957                         apos = rem.aframe_list[1].pos;
958                 if ( !r2 && vpos <= rem.vread)
959                         vpos = rem.vframe_list[1].pos;
960                 apack_size = apos - rem.aread; 
961                 vpack_size = vpos - rem.vread; 
962                 
963
964                 next_vdts = (uint32_t)((uint64_t)rem.vdts + rem.vpts_delay 
965                                   - rem.vpts_off) ;
966                 ok_video = ( rem.SCR < next_vdts);
967
968                 next_apts = (uint32_t)((uint64_t)rem.apts + rem.apts_delay 
969                                   - rem.apts_off) ;
970                 ok_audio = ( rem.SCR  < next_apts);
971
972                 asize = (apack_size > data_size ? data_size: apack_size);
973                 vsize = (vpack_size > data_size ? data_size: vpack_size);
974
975                 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);
976                 
977
978                 if( vbuf+vsize  < vbuf_max && vsize && ok_audio ){
979                         fprintf(stderr,"1 ");
980                         pos = write_video_pes( &rem, buf, &vpack_size);
981                         write( fout, buf, pos);
982                         vbuf += vpack_size;
983                         vbufn = add_pts( vbufl, rem.vdts, vpack_size, 
984                                          0, vbufn, 0);
985                         packets++;
986                 } else if ( abuf+asize < abuf_max && asize &&
987                             ok_video  ){
988                         fprintf(stderr,"2 ");
989                         pos = write_audio_pes( &rem, buf, &apack_size);
990                         write( fout, buf, pos);
991                         abuf += apack_size;
992                         abufn = add_pts( abufl, rem.apts, apack_size, 
993                                          0, abufn, 0);
994                         packets++;
995                 } else if ( abuf+asize < abuf_max && asize &&
996                             !ok_audio){
997                         fprintf(stderr,"3 ");
998                         pos = write_audio_pes( &rem, buf, &apack_size);
999                         write( fout, buf, pos);
1000                         abuf += apack_size;
1001                         abufn = add_pts( abufl, rem.apts, apack_size, 
1002                                          0, abufn, 0);
1003                         packets++;
1004                 } else if (vbuf+vsize  < vbuf_max && vsize &&
1005                            !ok_video){
1006                         fprintf(stderr,"4 ");
1007                         pos = write_video_pes( &rem, buf, &vpack_size);
1008                         write( fout, buf, pos);
1009                         vbuf += vpack_size;
1010                         vbufn = add_pts( vbufl, rem.vdts, vpack_size, 
1011                                          0, vbufn, 0);
1012                         packets++;
1013                 } else {
1014                 fprintf(stderr,"5 ");
1015                         pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 
1016                                               1, 1, 1, 0, 0, 0, 0, 0, 0);
1017
1018                         pos += write_pes_header( PADDING_STREAM, pack_size-pos,
1019                                                  0, buf+pos, 0);
1020                         write( fout, buf, pos);
1021                 }
1022
1023
1024                 //fprintf(stderr,"vbufn: %d  abufn: %d  ", vbufn,abufn);
1025                 //fprintf(stderr,"vbuf: %5d  abuf: %4d\n", vbuf,abuf);
1026
1027                 if (rem.SCR > rem.vdts+rem.vpts_off -rem.vpts_delay) 
1028                         rem.SCR = rem.vdts-rem.vpts_off;
1029                 rem.SCR = (uint32_t)((uint64_t) rem.SCR + SCR_inc);
1030
1031                 if ( rem.apts_off + rem.SCR < rem.apts_delay ) pts_d = 0;
1032                 else pts_d = (uint64_t) rem.SCR + rem.apts_off - rem.apts_delay;
1033                 abuf -= del_ptss( abufl, (uint32_t) pts_d, &abufn);
1034
1035                 if ( rem.vpts_off + rem.SCR < rem.vpts_delay ) pts_d = 0;
1036                 else pts_d = (uint64_t) rem.SCR + rem.vpts_off - rem.vpts_delay;
1037                 vbuf -= del_ptss( vbufl, (uint32_t) pts_d, &vbufn);
1038
1039                 print_info( &rem, 1);
1040                 //fprintf(stderr,"vbufn: %d  abufn: %d  ", vbufn,abufn);
1041                 //fprintf(stderr,"vbuf: %5d  abuf: %4d\n\n", vbuf,abuf);
1042
1043
1044         }
1045         pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, 
1046                               0, 0, 0, 0, 0, 0);
1047
1048         pos += write_pes_header( PADDING_STREAM, pack_size-pos-4, 0, 
1049                                  buf+pos, 0);
1050         pos = rem.pack_size-4;
1051         write( fout, buf, pos);
1052
1053         write( fout, mpeg_end, 4);
1054         fprintf(stderr,"\ndone\n");
1055 }
1056
1057
1058 typedef 
1059 struct pes_buffer_s{
1060         ringbuffy   pes_buffy;
1061         uint8_t     type;
1062         PTS_List    pts_list[MAX_PTS];
1063         FRAME_List  frame_list[MAX_FRAME];
1064         int         pes_size;
1065         uint64_t    written;
1066         uint64_t    read;
1067 } PESBuffer;
1068
1069
1070 void init_PESBuffer(PESBuffer *pbuf, int pes_size, int buf_size, uint8_t type)
1071 {
1072         init_framel( pbuf->frame_list);
1073         init_ptsl( pbuf->pts_list);
1074         ring_init( &pbuf->pes_buffy, buf_size);
1075         pbuf->pes_size = pes_size;
1076         pbuf->type = type; 
1077         pbuf->written = 0;
1078         pbuf->read = 0;
1079 }
1080         
1081
1082 #define MAX_PBUF 4
1083
1084 typedef
1085 struct remux_s{
1086         PESBuffer pbuf_list[MAX_PBUF];
1087         int num_pbuf;
1088 } REMUX;
1089
1090
1091 void init_REMUX(REMUX *rem)
1092 {
1093         rem->num_pbuf = 0;
1094 }
1095
1096
1097
1098 #define REPACK      2048 
1099 #define ABUF_SIZE   REPACK*1024
1100 #define VBUF_SIZE   REPACK*10240
1101
1102 void remux_main(uint8_t *buf, int count, void *pr)
1103 {
1104         int i, b;
1105         int bufsize = 0;
1106         p2p *p = (p2p *) pr;
1107         PESBuffer *pbuf;
1108         REMUX *rem = (REMUX *) p->data;
1109         uint8_t type = buf[3];
1110         int *npbuf = &(rem->num_pbuf);
1111
1112         switch ( type ){
1113         case PRIVATE_STREAM1:
1114                 bufsize = ABUF_SIZE;
1115         case VIDEO_STREAM_S ... VIDEO_STREAM_E:
1116                 if (!bufsize) bufsize = VBUF_SIZE;
1117         case AUDIO_STREAM_S ... AUDIO_STREAM_E:
1118                 if (!bufsize) bufsize = ABUF_SIZE;
1119                 b = -1;
1120                 for ( i = 0; i < *npbuf; i++){
1121                         if ( type == rem->pbuf_list[i].type ){
1122                                 b = i;
1123                                 break;
1124                         }
1125                 }
1126                 if (b < 0){
1127                         if ( *npbuf < MAX_PBUF ){
1128                                 init_PESBuffer(&rem->pbuf_list[*npbuf], 
1129                                                p->repack+6, bufsize, type);
1130                                 b = *npbuf;
1131                                 (*npbuf)++;
1132                         } else {
1133                                 fprintf(stderr,"Not enough PES buffers\n");
1134                                 exit(1);
1135                         }
1136                 }
1137                 break;
1138         default:
1139                 return;
1140         }
1141         
1142         pbuf = &(rem->pbuf_list[b]);
1143         if (ring_write(&(pbuf->pes_buffy),(char *)buf,count) != count){
1144                 fprintf(stderr,"buffer overflow type 0x%2x\n",type);
1145                 exit(1);
1146         } else {
1147                 pbuf->written += count;
1148                 if ((p->flag2 & PTS_DTS_FLAGS)){
1149                         uint32_t PTS = trans_pts_dts(p->pts);
1150                         add_pts(pbuf->pts_list, PTS, pbuf->written, 
1151                                 pbuf->written, 0, 0);
1152                 }
1153                 p->flag2 = 0;
1154         }
1155
1156 }
1157
1158 void output_mux(p2p *p) 
1159 {
1160         int i, filling;
1161         PESBuffer *pbuf;
1162         ringbuffy   *pes_buffy; 
1163         REMUX *rem = (REMUX *) p->data;
1164         int repack = p->repack;
1165         int npbuf = rem->num_pbuf;
1166
1167         for ( i = 0; i < npbuf; i++){
1168                 pbuf = &(rem->pbuf_list[i]);
1169                 pes_buffy = &pbuf->pes_buffy;
1170                 filling = pes_buffy->size - ring_rest(pes_buffy);
1171                 if (filling/(2 *repack)){
1172                         pbuf->read += ring_read_file(pes_buffy, p->fd1, 
1173                                                      (filling/repack)*repack);
1174                 }
1175         }
1176 }
1177
1178
1179
1180 #define SIZE 32768
1181
1182 void remux2(int fdin, int fdout)
1183 {
1184         p2p p;
1185         int count = 1;
1186         uint8_t buf[SIZE];
1187         uint64_t length = 0;
1188         uint64_t l = 0;
1189         int verb = 0;
1190         REMUX rem;
1191         
1192         init_p2p(&p, remux_main, REPACK);
1193         p.fd1 = fdout;
1194         p.data = (void *) &rem;
1195         
1196
1197         if (fdin != STDIN_FILENO) verb = 1; 
1198
1199         if (verb) {
1200                 length = lseek(fdin, 0, SEEK_END);
1201                 lseek(fdin,0,SEEK_SET);
1202         }
1203
1204         while (count > 0){
1205                 count = read(fdin,buf,SIZE);
1206                 l += count;
1207                 if (verb)
1208                         fprintf(stderr,"Writing  %2.2f %%\r",
1209                                 100.*l/length);
1210
1211                 get_pes(buf,count,&p,pes_repack);
1212                 output_mux(&p);
1213         }
1214                 
1215 }