1 /*  dvbcut
2     Copyright (c) 2005 Sven Over <svenover@svenover.de>
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-1307  USA
17 */
18 
19 /* $Id$ */
20 
21 #include <cstdlib>
22 #include <cstring>
23 #include <cstdio>
24 #include <strings.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <cassert>
30 #include "mpegmuxer.h"
31 
32 #ifndef O_BINARY
33 #define O_BINARY    0
34 #endif /* O_BINARY */
35 
36 /// video bitrate in bit/s
37 #define VIDEOBITRATE (9500000)
38 /// vbv buffer size in units of 1024 bytes
39 #define VBVBUFFERSIZE (224)
40 
41 struct streamlistsort
42   {
operator ()streamlistsort43   bool operator()(mpegmuxer::stream *a, mpegmuxer::stream *b)
44     {
45     return *a<*b;
46     }
47   };
48 
49 struct systemhdr_s
50   {
51   uint32_t system_header_start_code;
52   uint16_t header_length;
53   // unsigned marker_bit1 : 1;
54   // unsigned rate_bound : 22;
55   // unsigned marker_bit2 : 1;
56   // unsigned audio_bound : 6;
57   // unsigned fixed_flag : 1;
58   // unsigned CSPS_flag : 1;
59   uint32_t rate_etc;
60   // unsigned system_audio_lock_flag : 1;
61   // unsigned system_video_lock_flag : 1;
62   // unsigned marker_bit3 : 1;
63   // unsigned video_bound : 5;
64   uint8_t video_bound_etc;
65   // unsigned packet_rate_restriction_flag : 1;
66   // unsigned reserved_byte : 7;
67   uint8_t reserved_byte;
68   uint8_t stream_id1;
69   uint16_t stream1;
70   uint8_t stream_id2;
71   uint16_t stream2;
72   uint8_t stream_id3;
73   uint16_t stream3;
74   uint8_t stream_id4;
75   uint16_t stream4;
76   }
77 __attribute__((packed));
78 
79 
80 // **************************************************************************
81 // ***  mpegmuxer
82 
mpegmuxer(uint32_t audiostreammask,mpgfile & mpg,const char * filename,bool dvd,int packsize_bytes,int muxrate_bitsps)83 mpegmuxer::mpegmuxer(uint32_t audiostreammask, mpgfile &mpg, const char *filename, bool dvd,
84                      int packsize_bytes, int muxrate_bitsps) :
85     fd(-1), st(), muxrate(muxrate_bitsps/400), packsize(packsize_bytes), ptsoffset(0), aucounter(0),
86     systemhdr(0), systemhdrlen(0), pespacket_setlength(true),scr(0)
87   {
88   if (packsize<MINPACKSIZE)
89     packsize=0;
90   scrpack=int(27.e6/double(muxrate*50)*packsize+0.9999);
91 
92   st[VIDEOSTREAM]=new stream(streamtype::mpeg2video,0xe0,232<<10,232<<10,true);
93   strpres[VIDEOSTREAM]=true;
94 
95   int audiobuffersize=dvd?(4<<10):(48<<10);
96   for (int i=0;i<mpg.getaudiostreams();++i)
97     if (audiostreammask & (1u<<i)) {
98       streamtype::type t = mpg.getstreamtype(audiostream(i));
99       if (t==streamtype::ac3audio)
100         st[audiostream(i)]=new stream(t, 0x180+i,
101                                       audiobuffersize,58<<10,true);
102       /* not supported yet:
103       else if (t==streamtype::dtsaudio)
104         st[audiostream(i)]=new stream(t, 0x188+i,
105                                       audiobuffersize,58<<10,true);
106       */
107       else
108         st[audiostream(i)]=new stream(t, 0xc0+i,
109                                       audiobuffersize,audiobuffersize,false);
110       strpres[audiostream(i)]=true;
111       }
112 
113   systemhdrlen=dvd ? 2034 : 24; // include DVD navigation packets if dvd set
114   systemhdr=malloc(systemhdrlen);
115   bzero(systemhdr,systemhdrlen);
116 
117   *(systemhdr_s *)systemhdr = (systemhdr_s) {
118                                 mbo32(0x000001bb),mbo16(18),
119                                 //1,muxrate,1,mpg.getaudiostreams(),0,0,
120                                 htom32(0x80000100 | ((muxrate&0x3fffff)<<9) | (mpg.getaudiostreams()<<2)),
121                                 //1,1,1,1,
122                                 0xe1,
123                                 //0,0x7f,
124                                 0x7f,
125                                 0xb9,mbo16(0xe000|232),0xb8,mbo16(0xc000|32),
126                                 0xbd,mbo16(0xe000|58),0xbf,mbo16(0xe000|2)
127                                 };
128 
129   if (dvd) { // dvd nav packets
130     *(uint32_t*)((char*)systemhdr+24)=mbo32(0x000001bf);
131     *(uint16_t*)((char*)systemhdr+28)=mbo16(980);
132     *(uint32_t*)((char*)systemhdr+1010)=mbo32(0x000001bf);
133     *(uint16_t*)((char*)systemhdr+1014)=mbo16(1018);
134     }
135 
136   // total size of all buffers: 232kB video + 4kB per mpeg audio stream
137   double allbuffers(double((232<<10)+mpg.getaudiostreams()*(4<<10)));
138   allbuffers*=1.05; // 5% assumed muxing overhead
139   ptsoffset=pts_t(90000.*(allbuffers/50./muxrate))+90;
140 
141   if (!strncmp(filename, "pipe:", 5))
142     fd = atoi(filename+5);
143   else
144     fd=::open(filename,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666);
145   }
146 
~mpegmuxer()147 mpegmuxer::~mpegmuxer()
148   {
149   if (fd>=0) {
150     flush(true);
151     ::close(fd);
152     }
153 
154   for(int i=0;i<MAXAVSTREAMS;++i)
155     if (st[i])
156       delete st[i];
157 
158   if (systemhdr)
159     free(systemhdr);
160   }
161 
putpacket(int str,const void * data,int len,pts_t pts,pts_t dts,uint32_t flags)162 bool mpegmuxer::putpacket(int str, const void *data, int len, pts_t pts, pts_t dts, uint32_t flags)
163   {
164   stream * const s=st[str];
165   if (!s)
166     return false;
167   if (len == 0) {
168 	// I'm not sure why this happens, but it does. --mr
169 	fprintf(stderr, "mpegmuxer::putpacket called with zero length, str=%d\n", str);
170 	return false;
171   }
172   pts+=ptsoffset;
173   dts+=ptsoffset;
174   au *newau=new au(data,len,pts,dts,flags);
175 
176   if (s->type==streamtype::mpeg2video) {
177     uint8_t *audata=(uint8_t*) newau->getdata();
178 
179     //     if (0) //
180     for (int j=0;j+11<len;) {
181       uint8_t *d=audata+j;
182       if (d[2]&0xfe)
183         j+=3;
184       else
185         if (((*(u_int32_t*)&d[0])&mbo32(0xffffff00))==mbo32(0x00000100)) {
186           if (d[3]==0x00) // picture header
187             {
188             // vbv delay := 0xffff
189             d[5]|=0x07;
190             d[6]=0xff;
191             d[7]|=0xf8;
192             break;
193             } else if (d[3]==0xb3) // sequence header
194             {
195             d[8]=(VIDEOBITRATE/400) >> 10;
196             d[9]=((VIDEOBITRATE/400) >> 2) & 0xff;
197             d[10]=(((VIDEOBITRATE/400) << 6)&0xc0)|0x20|(((VBVBUFFERSIZE/2)>>5)&0x1f);
198             d[11]=(d[11]&0x07)|((VBVBUFFERSIZE/2)<<3);
199             j+=12;
200             } else if (d[3]==0xb5) // extension
201             {
202             if ((d[4]&0xf0) == 0x10) // sequence extension
203               {
204               // set bitrate_extension and vbv_buffer_size_extension to 0
205               d[6]&=0xe0;
206               d[7]=0x01;
207               d[8]=0;
208               j+=10;
209               } else
210               j+=5;
211             } else
212             j+=4;
213           } else
214           ++j;
215       }
216     }
217 
218   s->aulist.push_back(newau);
219   s->bufferremovals.push_back(bufferremoval(pts2scr(dts),len));
220 
221   if (++aucounter>=300) {
222     aucounter=0;
223     return flush(false);
224     }
225 
226   return true;
227   }
228 
flush(bool flushall)229 bool mpegmuxer::flush(bool flushall)
230   {
231   const pts_t dts_safetymargin=2*90000; // 2 seconds
232   pts_t maxdts=-1;
233 
234   if (!flushall) {
235     maxdts=0;
236     for(int i=0;i<MAXAVSTREAMS;++i)
237       if (st[i] && !st[i]->aulist.empty() && st[i]->aulist.back()->getdts()>maxdts )
238         maxdts=st[i]->aulist.back()->getdts();
239 
240     // maxdts is the maximal DTS in all access units available by now
241     // we subtract a safety margin from that value
242     maxdts-=dts_safetymargin;
243     // maxdts is now the max DTS value up to which we process access units
244 
245     // we want to have at least one second worth of material
246     if (maxdts<90000)
247       return true;
248     }
249 
250   packetizer(VIDEOSTREAM,maxdts);
251 
252   for(int i=audiostream(0);i<=audiostream(MAXAUDIOSTREAMS-1);++i)
253     if (st[i])
254       packetizer(i,maxdts);
255 
256   for(int i=0;i<MAXAVSTREAMS;++i) {
257     stream * const s=st[i];
258     if (!s || st[i]->packlist.empty() )
259       continue;
260 
261     scr_t maxscr=s->packlist.back()->getmaxscr();
262     std::list<pack*>::reverse_iterator it=s->packlist.rbegin();
263     for(++it;it!=s->packlist.rend();++it) {
264       maxscr-=packsize?scrpack:int(27.e6/double(muxrate*50)*(*it)->getsize()+0.9999);
265       (*it)->setmaxscr(maxscr);
266       maxscr=(*it)->getmaxscr();
267       }
268     }
269 
270   // access units have been put into packs, fine.
271   // now we multiplex these packs into a program stream. Again, we
272   // have a safety margin (one second this time).
273   scr_t stopscr=maxdts<0?-1:pts2scr(maxdts-90000);
274   std::list<stream*> streamlist;
275 
276   for(int i=0;i<MAXAVSTREAMS;++i)
277     if (st[i] && !st[i]->packlist.empty()) // && st[i]->packlist.front()->getmaxscr()<stopscr)
278       streamlist.push_back(st[i]);
279 
280   streamlist.sort(streamlistsort());
281 
282   while (!streamlist.empty() &&
283          (*(streamlist.front())<stopscr || (stopscr<0 && !streamlist.front()->packlist.empty()))) {
284     std::list<stream*>::iterator it=streamlist.begin();
285     std::list<stream*>::iterator minscrit=streamlist.end();
286     scr_t minscr=streamlist.front()->packlist.front()->getminscr();
287 
288     for(;it!=streamlist.end() && !(*it)->packlist.empty();++it)
289       if ((*it)->packlist.front()->getminscr()<=scr)
290         break;
291       else if ((*it)->packlist.front()->getminscr()<minscr) {
292         minscr=(*it)->packlist.front()->getminscr();
293         minscrit=it;
294         }
295 
296     if ((it==streamlist.end()) || ((*it)->packlist.empty())) {
297       while (minscr-scr>13500000) {
298         pack p(packsize,0,muxrate,0);
299         scr+=13500000;
300         p.setscr(scr);
301         if (!p.write(fd)) return false;
302         }
303 
304       scr=minscr;
305       if (minscrit!=streamlist.end())
306         it=minscrit;
307       else
308         continue;
309       }
310 
311     stream *s=*it;
312     assert(!s->packlist.empty());
313     pack *p=s->packlist.front();
314 
315     if (s->getfill()<0) {
316       fprintf(stderr,"stream %d filllevel: %d\n",s->getid(),s->getfill());
317       }
318 
319     if (!s->bufferremovals.empty()) {
320       if (s->bufferremovals.back().scr()<=scr) {
321         s->zerofill();
322         s->bufferremovals.clear();
323         } else
324         while (!s->bufferremovals.empty()) {
325           bufferremoval &r=s->bufferremovals.front();
326           if (r.scr()>scr)
327             break;
328           s->unfill(r.bytes());
329           s->bufferremovals.pop_front();
330           }
331 
332 
333       // Buffer full?
334       if (p->getaupayloadlen()>s->getbuffree()) {
335 
336         int freespace=s->getbuffree();
337 
338         //scr_t minscr=p->getminscr();
339 
340         for(std::list<bufferremoval>::iterator it=s->
341             bufferremovals.begin();
342             it!=s->bufferremovals.end();
343             ++it) {
344           scr_t stepminscr=it->scr()+2700; //-scr_t(27.e6*freespace/double(muxrate*50));
345 
346           p->setminscr(stepminscr);
347           freespace+=it->bytes();
348           if (freespace>=p->getaupayloadlen())
349             break;
350           }
351 
352         if (p->getminscr()
353             >scr)
354           continue;
355         }
356       }
357 
358     p->setscr(scr);
359     scr+=packsize?scrpack:int(27.e6/double(muxrate*50)*p->getsize()+0.9999);
360     if (scr>p->getmaxscr())
361       fprintf(stderr,"Muxer problem: %s > %s (dts:%s) s->getbuffree():%d\n",
362               ptsstring(scr2pts(scr)).c_str(),
363               ptsstring(scr2pts(p->getmaxscr())).c_str(),
364               ptsstring(p->getdts()).c_str(),
365               s->getbuffree() );
366     if (!p->write(fd)) return false;
367     if (p->getaupayloadlen()>0) {
368       s->fill(p->getaupayloadlen());
369       }
370     s->packlist.pop_front();
371     delete p;
372 
373     streamlist.erase(it);
374     for(it=streamlist.begin();it!=streamlist.end();++it)
375       if (*s<**it)
376         break;
377     streamlist.insert(it,s);
378     }
379 
380   return true;
381   }
382 
packetizer(int str,pts_t maxdts)383 void mpegmuxer::packetizer(int str,pts_t maxdts)
384   {
385   bool const video=(str==VIDEOSTREAM);
386   stream * const s=st[str];
387 
388   while (!s->aulist.empty() && (maxdts<0 || s->aulist.front()->getdts()<maxdts)) {
389     au *a=s->aulist.front();
390     bool headerpts(false), headerdts(false), headerext(false);
391 
392     if (video) {
393       if (!a->incomplete() && (a->getflags()&MUXER_FLAG_KEY)) // key frame
394         {
395         const void *data=systemhdr;
396         int slen=systemhdrlen;
397         while (slen>0)
398           {
399           pack * const p=new pack(packsize, slen, muxrate, a->getdts());
400           memcpy(p->getpayload(),data,p->getpayloadlen());
401           slen-=p->getpayloadlen();
402           data=(const void*)((const char*)data+p->getpayloadlen());
403           s->packlist.push_back(p);
404           p->nopayload();
405           }
406         headerpts=true;
407         if (a->getdts() != a->getpts())
408           headerdts=true;
409         headerext=true;
410         }
411       } else if (s->type==streamtype::mpegaudio) { // audio
412       if ((!a->incomplete())||(++s->aulist.begin()!=s->aulist.end()))
413         headerpts=true;
414       if (!a->incomplete())
415         headerext=true;
416       } else if (s->type==streamtype::ac3audio) { // audio
417       if ((!a->incomplete())||(++s->aulist.begin()!=s->aulist.end()))
418         headerpts=true;
419       headerext=((s->packet%1000)==0);
420       }
421 
422     int headerlen=0;
423     if (headerpts)
424       headerlen+=5;
425     if (headerdts)
426       headerlen+=5;
427     if (headerext)
428       headerlen+=3;
429     bool isprivatestream(s->id>=0x100 && s->id<0x300);
430     if (isprivatestream)
431       ++headerlen;
432     if (s->type==streamtype::ac3audio)
433       headerlen+=3;
434     /* not supported yet:
435     if (s->type==streamtype::dtsaudio)
436       headerlen+=3;
437     */
438     int len=9+headerlen+a->getsize();
439     if (pespacket_setlength)
440       len+=9*((len-10)/65532);
441 
442     if (!video || packsize) {
443       int maxsize=9+headerlen+s->getbufsize()*3/4;
444       if (pespacket_setlength)
445         maxsize+=9*((maxsize-10)/65532);
446       if (packsize && maxsize>pack::maxpayload(packsize))
447         maxsize=pack::maxpayload(packsize);
448       if (pespacket_setlength && maxsize>65541 && maxsize%65541<=9)
449         maxsize-=maxsize%65541;
450 
451       std::list<au*>::iterator it=s->aulist.begin();
452       ++it;
453 
454       while (it!=s->aulist.end() && len<maxsize-16) { // -16
455         au * const aa=*it;
456         ++it;
457         // don't start next sequence within this pack
458         if (video&&(aa->getflags()&MUXER_FLAG_KEY))
459           break;
460         // no DTS in this packet shall be 0.7s or more after the first DTS
461         if (aa->getdts()-a->getdts()>=63000)
462           break;
463         int newlen;
464         if (pespacket_setlength) {
465           newlen=len-9*((len-10)/65541)+aa->getsize();
466           newlen+=9*((newlen-10)/65532);
467           } else
468           newlen=len+aa->getsize();
469         if (s->type==streamtype::mpegaudio && (newlen>maxsize) && (len>maxsize-50))
470           break;
471         len=newlen;
472         }
473 
474       if (packsize && len>pack::maxpayload(packsize))
475         len=pack::maxpayload(packsize);
476       }
477     //        else {
478     //       int maxsize=9+headerlen+s->getbufsize()*3/4;
479     //       if (packsize && maxsize>pack::maxpayload(packsize))
480     //         maxsize=pack::maxpayload(packsize);
481     //       std::list<au*>::iterator it=s->aulist.begin();
482     //       ++it;
483     //
484     //       while (it!=s->aulist.end()) {
485     //         au * const aa=*it;
486     //         // no DTS in this packet shall be 0.7s or more after the first DTS
487     //         if (aa->getdts()-a->getdts()>=63000)
488     //           break;
489     //         if (len+aa->getsize()>maxsize)
490     //           break;
491     //           if (pespacket_setlength) {
492     //             len=len-9*((len-6)/65545)+aa->getsize();
493     //             len+=9*((len-6)/65536);
494     //             } else
495     //             len+=aa->getsize();
496     //         }
497     //       }
498 
499 
500     int pes_padding = 0;
501     if (packsize) {
502       int maxpayload = pack::maxpayload(packsize);
503       assert(len <= maxpayload);
504       if (maxpayload - len < 8)
505         pes_padding = maxpayload - len;
506       headerlen += pes_padding;
507       len += pes_padding;
508       }
509 
510     pack * const p=new pack(packsize,len,muxrate,a->getdts());
511     s->packlist.push_back(p);
512     ++s->packet;
513     len=p->getpayloadlen();
514     char *data=(char*)p->getpayload();
515 
516     while (a && (len>9+headerlen)) {
517       int plen=len-6;
518       if (pespacket_setlength && plen>65535)
519         plen=65535;
520 
521       *(uint32_t*)data=s->getstartcode();
522       data+=4;
523       *(uint16_t*)data=pespacket_setlength ? htom16(plen) : 0;
524       data+=2;
525       len-=6;
526 
527       //       *(data++)=((!a->incomplete())&&(s->type!=streamtype::mpeg2video || (a->getflags()&MUXER_FLAG_KEY)))?0x85:0x81;
528       *(data++)=a->incomplete()?0x81:0x85;
529       *(data++)=(headerpts?0x80:0)|(headerdts?0x40:0)|(headerext?0x01:0);
530       int officialheaderlen=headerlen;
531       if (isprivatestream)
532         --officialheaderlen;
533       if (s->type==streamtype::ac3audio)
534         officialheaderlen-=3;
535       /* not supported yet:
536       if (s->type==streamtype::dtsaudio)
537         officialheaderlen-=3;
538       */
539       *(data++)=officialheaderlen;
540       len-=3;
541       plen-=3;
542 
543       if (headerpts) {
544         pts_t pts=a->getpts();
545         if (a->incomplete()) {
546           std::list<au*>::iterator it=++s->aulist.begin();
547           if (it!=s->aulist.end())
548             pts=(*it)->getpts();
549           }
550         uint32_t pts32=pts&0xffffffff;
551         *(data++)=(headerdts?0x31:0x21)|(uint32_t(pts>>29)&0x0e);
552         *(data++)=pts32>>22;
553         *(data++)=(pts32>>14)|1;
554         *(data++)=pts32>>7;
555         *(data++)=(pts32<<1)|1;
556         plen-=5;
557         len-=5;
558         headerpts=false;
559         headerlen-=5;
560         }
561       if (headerdts) {
562         pts_t dts=a->getdts();
563         uint32_t dts32=dts&0xffffffff;
564         *(data++)=0x11|(uint32_t(dts>>29)&0x0e);
565         *(data++)=dts32>>22;
566         *(data++)=(dts32>>14)|1;
567         *(data++)=dts32>>7;
568         *(data++)=(dts32<<1)|1;
569         plen-=5;
570         len-=5;
571         headerdts=false;
572         headerlen-=5;
573         }
574       if (headerext) {
575         *(data++)=0x10; // P-STD_buffer_flag
576         *(uint16_t*)data=s->getpstdbuffer();
577         data+=2;
578         plen-=3;
579         len-=3;
580         headerext=false;
581         headerlen-=3;
582         }
583       if (pes_padding > 0) {
584         memset(data, 0xff, pes_padding);
585         data += pes_padding;
586         headerlen -= pes_padding;
587         plen -= pes_padding;
588         len -= pes_padding;
589         pes_padding = 0;
590         }
591       if (isprivatestream) {
592         *(data++)=s->id & 0xff;
593         --plen;
594         --len;
595         }
596 
597       uint8_t *framestarts=0;
598       uint16_t *framestartoffset=0;
599       if (s->type==streamtype::ac3audio) {
600         framestarts=(uint8_t*)data;
601         *(data++)=0;
602         framestartoffset=(uint16_t*)data;
603         *(data++)=0;
604         *(data++)=0;
605         plen-=3;
606         len-=3;
607         }
608 
609       while (plen>0) {
610         int copy=a->getsize();
611         if (copy>plen)
612           copy=plen;
613 
614         if (framestarts && !a->incomplete()) {
615           if (*framestarts==0 && framestartoffset)
616             *framestartoffset=htom16((data-(char*)framestartoffset)-1);
617           ++*framestarts;
618           }
619         memcpy(data,a->getdata(),copy);
620         data+=copy;
621         len-=copy;
622         plen-=copy;
623         a->addpos(copy);
624         p->addaupayload(copy);
625 
626         if (video)
627           p->setmaxscr(pts2scr(a->getdts()));
628 
629         if (a->getsize()==0) {
630           s->aulist.pop_front();
631           delete a;
632           if (s->aulist.empty()) {
633             a=0;
634             break;
635             }
636           a=s->aulist.front();
637           p->setlastdts(a->getdts());
638           }
639         }
640       }
641 
642     if (len) {
643       fprintf(stderr,"str=%d len=%d aulist.size=%lu packlist.size=%lu\n",
644 	str,len,s->aulist.size(),s->packlist.size());
645       assert(len==0);
646       }
647     }
648   }
649 
650 
651 // **************************************************************************
652 // ***  mpegmuxer::au (access units)
653 
au(const void * _data,int _size,pts_t _pts,pts_t _dts,int _flags)654 mpegmuxer::au::au(const void *_data,int _size, pts_t _pts, pts_t _dts, int _flags) :
655     data(0), size(_size), pts(_pts), dts(_dts), flags(_flags), pos(0)
656   {
657   data=malloc(size);
658   memcpy(data,_data,size);
659   }
~au()660 mpegmuxer::au::~au()
661   {
662   if (data)
663     free(data);
664   }
665 
666 // **************************************************************************
667 // ***  mpegmuxer::pack
668 
pack(int packsize,int payloadsize,int muxrate,pts_t _dts)669 mpegmuxer::pack::pack(int packsize, int payloadsize, int muxrate, pts_t _dts) :
670     data(0), size(packsize), minscr(pts2scr(_dts-DTSMAXDELAY)), maxscr(pts2scr(_dts)),
671     dts(_dts),
672     payloadpos(14),payloadlen(payloadsize),aupayloadlen(0)
673   {
674   if (size<MINPACKSIZE) // considered as unspecified packsize
675     {
676     if (payloadlen<0)
677       payloadlen=0;
678     size=payloadlen+14; // big enough to host payload
679     } else // fixed packsize
680     if (payloadlen>size-14)
681       payloadlen=size-14;
682     else
683       if (payloadlen<0)
684         payloadlen=0;
685 
686   if (size-payloadlen<21)
687     payloadpos=size-payloadlen;
688   else
689     payloadpos=14;
690 
691   data=malloc(size);
692 
693   *(uint32_t*)data=mbo32(0x000001ba); // pack_start_code
694   *(uint32_t*)((char*)data+10)=htom32((muxrate<<10)|0x00000300|(payloadpos-14)); // program_mux_rate and pack_stuffing_length
695   for(int i=14;i<payloadpos;++i)
696     ((unsigned char*)data)[i]=0xff;
697 
698   int pos=payloadpos+payloadlen;
699   while (pos+6<=size) // add padding packet
700     {
701     void *pad=(void*)((char*)data+pos);
702     int padlen=size-pos-6;
703     if (padlen>65535)
704       {
705       if (padlen>=65541)
706         padlen=65535;
707       else
708         padlen-=6;
709       }
710     *(uint32_t*)pad=mbo32(0x000001be);
711     *(uint16_t*)((char*)pad+4)=htom16(padlen);
712     memset((char*)pad+6,0xff,padlen);
713     pos+=padlen+6;
714     }
715   while (pos<size) // should never happen
716     ((unsigned char*)data)[pos++]=0xff;
717   }
718 
~pack()719 mpegmuxer::pack::~pack()
720   {
721   if (data)
722     free(data);
723   }
724 
setscr(scr_t scr)725 void mpegmuxer::pack::setscr(scr_t scr)
726   {
727   if (!data || size<10)
728     return;
729   uint8_t *d=(uint8_t*)data+4;
730   uint64_t scrb=scr/300;
731   uint32_t scrx=scr%300;
732   uint32_t scrb32=scrb&0xffffffff;
733 
734   d[0]=(uint32_t(scrb>>27)&0x38)|((scrb32>>28)&0x03)|0x44;
735   d[1]=scrb32>>20;
736   d[2]=((scrb32>>12)&0xf8)|0x04|((scrb32>>13)&0x03);
737   d[3]=scrb32>>5;
738   d[4]=((scrb32<<3)&0xf8)|0x04|((scrx>>7)&0x03);
739   d[5]=scrx<<1|0x01;
740   }
741 
742 bool
write(int fd)743 mpegmuxer::pack::write(int fd) {
744   uint8_t *d = (uint8_t*)data;
745   size_t len = size;
746   ssize_t n = 0;
747 
748   while (len > 0 && (n = ::write(fd, d, len)) > 0) {
749     len -= n;
750     d += n;
751   }
752   if (len == 0) {
753     return true;
754   }
755   if (n == 0) {
756     fprintf(stderr, "zero-length write - disk full?\n");
757   }
758   else {
759     perror("write");
760   }
761   return false;
762 }
763