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