MythTV master
pes.cpp
Go to the documentation of this file.
1/*
2 * pes.c: MPEG PES functions for replex
3 *
4 *
5 * Copyright (C) 2003 Marcus Metzler <mocm@metzlerbros.de>
6 * Metzler Brothers Systementwicklung GbR
7 * Changes to use MythTV logging
8 * Copyright (C) 2011 Gavin Hurlbut <ghurlbut@mythtv.org>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * General Public License for more details.
20 *
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
26 *
27 */
28
29#include <array>
30#include <cstdio>
31#include <cstdlib>
32#include <cstring>
33
34#ifdef _WIN32
35#include <winsock2.h>
36#else
37#include <netinet/in.h>
38#endif
39
40#include "pes.h"
42
43void printpts(int64_t pts)
44{
45 int negative = 0;
46 if (pts < 0){
47 negative = 1;
48 pts = -pts;
49 }
50 pts = pts/300;
51 pts &= (MAX_PTS-1);
52 LOG(VB_GENERAL, LOG_INFO, QString("%1%2:%3:%4.%5")
53 .arg(negative ? "-" : "")
54 .arg((unsigned int)(pts/90000.0)/3600, 2,10,QChar('0'))
55 .arg(((unsigned int)(pts/90000.0)%3600)/60, 2,10,QChar('0'))
56 .arg(((unsigned int)(pts/90000.0)%3600)%60, 2,10,QChar('0'))
57 .arg((((unsigned int)(pts/9.0)%36000000)%600000)%10000, 4,10,QChar('0')));
58}
59
60void printptss(int64_t pts)
61{
62 int negative = 0;
63 if (pts < 0){
64 negative = 0;
65 pts = -pts;
66 }
67 pts = pts/300;
68 pts &= (MAX_PTS-1);
69 LOG(VB_GENERAL, LOG_INFO, QString("%1%2:%3:%4.%5")
70 .arg(negative ? "-" : "")
71 .arg((unsigned int)(pts/90000.0)/3600, 2,10,QChar('0'))
72 .arg(((unsigned int)(pts/90000.0)%3600)/60, 2,10,QChar('0'))
73 .arg(((unsigned int)(pts/90000.0)%3600)%60, 2,10,QChar('0'))
74 .arg((((unsigned int)(pts/90.0)%3600000)%60000)%1000, 3,10,QChar('0')));
75}
76
77/* use if you know that ptss are close and may overflow */
78int64_t ptsdiff(uint64_t pts1, uint64_t pts2)
79{
80 switch (ptscmp(pts1, pts2)){
81 case 0:
82 return 0;
83 break;
84
85 case 1:
86 case -2:
87 return (pts1 -pts2);
88 break;
89
90 case 2:
91 return (pts1 + MAX_PTS2 -pts2);
92 break;
93
94 case -1:
95 return (pts1 - (pts2+ MAX_PTS2));
96 break;
97
98 }
99
100 return 0;
101}
102
103/* use, if you need an unsigned result in pts range */
104uint64_t uptsdiff(uint64_t pts1, uint64_t pts2)
105{
106 int64_t diff = pts1 - pts2;
107
108 if (diff < 0){
109 diff = MAX_PTS2 +diff;
110 }
111 return diff;
112}
113
114int ptscmp(uint64_t pts1, uint64_t pts2)
115{
116 int ret = -1;
117
118 if (pts1 > pts2){
119 if ((pts1 - pts2) > MAX_PTS2/2)
120 ret = -1;
121 else
122 ret = 1;
123 } else if (pts1 == pts2) {
124 ret = 0;
125 } else {
126 if ((pts2 - pts1) > MAX_PTS2/2)
127 ret = 2;
128 else
129 ret = -2;
130 }
131#if 0
132 LOG(VB_GENERAL, LOG_INFO,
133 QString("PTSCMP: %1 %2 %3\n").arg(pts1).arg(pts2).arg(ret));
134 printpts(pts1);
135 printpts(pts2);
136#endif
137 return ret;
138}
139
140uint64_t ptsadd(uint64_t pts1, uint64_t pts2)
141{
142 ptsinc(&pts1,pts2);
143 return pts1;
144
145}
146
147void init_pes_in(pes_in_t *p, int t, ringbuffer *rb, int wi){
148 p->type = t;
149 p->found = 0;
150 p->cid = 0;
151 p->mpeg = 0;
152 p->withbuf = wi;
153
154 if (p->withbuf && p->buf.empty()){
155 p->buf.resize(MAX_PLENGTH);
156 } else if (rb) {
157 p->rbuf = rb;
158 }
159 if (p->rbuf) p->ini_pos = ring_wpos(p->rbuf);
160 p->done = false;
161 memset(p->pts, 0 , 5);
162 memset(p->dts, 0 , 5);
163}
164
165
166void get_pes (pes_in_t *p, uint8_t *buf, int count, void (*func)(pes_in_t *p))
167{
168 unsigned short *pl = nullptr;
169 bool done = false;
170
171 std::array<uint8_t,3> headr { 0x00, 0x00, 0x01} ;
172 while (!done)
173 {
174 int c=0;
175 done = true;
176 while (c < count && (!p->mpeg ||
177 (p->mpeg == 2 && p->found < 9))
178 && (p->found < 5 || !p->done)){
179 switch ( p->found ){
180 case 0:
181 case 1:
182 if (buf[c] == 0x00) p->found++;
183 else p->found = 0;
184 c++;
185 break;
186 case 2:
187 if (buf[c] == 0x01) p->found++;
188 else if (buf[c] == 0){
189 p->found = 2;
190 } else {
191 p->found = 0;
192 }
193 c++;
194 break;
195 case 3:
196 p->cid = 0;
197 switch (buf[c]){
198 case PROG_STREAM_MAP:
199 case PRIVATE_STREAM2:
200 case PROG_STREAM_DIR:
201 case ECM_STREAM :
202 case EMM_STREAM :
203 case PADDING_STREAM :
204 case DSM_CC_STREAM :
205 case ISO13522_STREAM:
206 p->done = true;
207 [[fallthrough]];
208 case PRIVATE_STREAM1:
211 p->found++;
212 p->cid = buf[c];
213 c++;
214 break;
215 default:
216 case PACK_START:
217 case SYS_START:
218 p->found = 0;
219 c++;
220 break;
221 }
222 break;
223
224
225 case 4:
226 if (count-c > 1){
227 pl = (unsigned short *) (buf+c);
228 p->plength = ntohs(*pl);
229 p->plen[0] = buf[c];
230 c++;
231 p->plen[1] = buf[c];
232 c++;
233 p->found+=2;
234 } else {
235 p->plen[0] = buf[c];
236 p->found++;
237 return;
238 }
239 break;
240 case 5:
241 p->plen[1] = buf[c];
242 c++;
243 pl = (unsigned short *) p->plen;
244 p->plength = ntohs(*pl);
245 p->found++;
246 break;
247
248
249 case 6:
250 if (!p->done){
251 p->flag1 = buf[c];
252 c++;
253 p->found++;
254 if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2;
255 else {
256 LOG(VB_GENERAL, LOG_ERR,
257 "Error: THIS IS AN MPEG1 FILE");
258 exit(1);
259 }
260 }
261 break;
262
263 case 7:
264 if ( !p->done && p->mpeg == 2){
265 p->flag2 = buf[c];
266 c++;
267 p->found++;
268 }
269 break;
270
271 case 8:
272 if ( !p->done && p->mpeg == 2){
273 p->hlength = buf[c];
274 c++;
275 p->found++;
276 }
277 break;
278
279 default:
280
281 break;
282 }
283 }
284
285 if (!p->plength) p->plength = MMAX_PLENGTH-6;
286
287
288 if ( p->done || (p->mpeg == 2 && p->found >= 9) ){
289 switch (p->cid){
290
293 case PRIVATE_STREAM1:
294
295 if (p->withbuf){
296 memcpy(p->buf.data(), headr.data(), 3);
297 p->buf[3] = p->cid;
298 memcpy(p->buf.data()+4,p->plen,2);
299 } else {
300 memcpy(p->hbuf, headr.data(), 3);
301 p->hbuf[3] = p->cid;
302 memcpy(p->hbuf+4,p->plen,2);
303 }
304
305 if (p->found == 9){
306 if (p->withbuf){
307 p->buf[6] = p->flag1;
308 p->buf[7] = p->flag2;
309 p->buf[8] = p->hlength;
310 } else {
311 p->hbuf[6] = p->flag1;
312 p->hbuf[7] = p->flag2;
313 p->hbuf[8] = p->hlength;
314 }
315 }
316
317 if ( (p->flag2 & PTS_ONLY) && p->found >= 9 && p->found < 14){
318 while (c < count && p->found < 14){
319 p->pts[p->found-9] = buf[c];
320 if (p->withbuf)
321 p->buf[p->found] = buf[c];
322 else
323 p->hbuf[p->found] = buf[c];
324 c++;
325 p->found++;
326 }
327 if (c == count) return;
328 }
329
330 if (((p->flag2 & PTS_DTS) == 0xC0) && p->found >= 14 && p->found < 19){
331 while (c < count && p->found < 19){
332 p->dts[p->found-14] = buf[c];
333 if (p->withbuf)
334 p->buf[p->found] = buf[c];
335 else
336 p->hbuf[p->found] = buf[c];
337 c++;
338 p->found++;
339 }
340 if (c == count) return;
341 }
342
343
344 while (c < count && p->found < p->plength+6){
345 int l = count -c;
346 if (l+p->found > p->plength+6)
347 l = p->plength+6-p->found;
348 if (p->withbuf)
349 memcpy(p->buf.data()+p->found, buf+c, l);
350 else {
351 if ( p->found <
352 (unsigned int)p->hlength+9 ){
353 int rest = p->hlength+9-p->found;
354 memcpy(p->hbuf+p->found, buf+c, rest);
355 if (ring_write(p->rbuf, buf+c+rest,
356 l-rest) <0){
357 exit(1);
358 }
359 } else {
360 if (ring_write(p->rbuf, buf+c, l)<0){
361 LOG(VB_GENERAL, LOG_ERR,
362 QString("ring buffer overflow %1")
363 .arg(p->rbuf->size));
364 exit(1);
365 }
366 }
367 }
368
369 p->found += l;
370 c += l;
371 }
372 if(p->found == p->plength+6){
373 func(p);
374 }
375 break;
376 }
377
378 if ( p->done ){
379 if( p->found + count - c < p->plength+6){
380 p->found += count-c;
381 c = count;
382 } else {
383 c += p->plength+6 - p->found;
384 p->found = p->plength+6;
385 }
386 }
387
388 if (p->plength && p->found == p->plength+6) {
389 init_pes_in(p, p->type, nullptr, p->withbuf);
390 if (c < count) {
391 done = false;
392 count -= c;
393 buf += c;
394 }
395 }
396 }
397 }
398}
399
400
401#if 0
402static uint32_t scr_base_ps(const uint8_t *scr)
403{
404 uint32_t base = 0;
405 uint8_t *buf = (uint8_t *)&base;
406
407 buf[0] |= (uint8_t)((scr[0] & 0x18) << 3);
408 buf[0] |= (uint8_t)((scr[0] & 0x03) << 4);
409 buf[0] |= (uint8_t)((scr[1] & 0xF0) >> 4);
410
411 buf[1] |= (uint8_t)((scr[1] & 0x0F) << 4);
412 buf[1] |= (uint8_t)((scr[2] & 0xF0) >> 4);
413
414 buf[2] |= (uint8_t)((scr[2] & 0x08) << 4);
415 buf[2] |= (uint8_t)((scr[2] & 0x03) << 5);
416 buf[2] |= (uint8_t)((scr[3] & 0xF8) >> 3);
417
418 buf[3] |= (uint8_t)((scr[3] & 0x07) << 5);
419 buf[3] |= (uint8_t)((scr[4] & 0xF8) >> 3);
420
421 base = ntohl(base);
422 return base;
423}
424
425static uint16_t scr_ext_ps(const uint8_t *scr)
426{
427 short ext = 0;
428
429 ext = (short)(scr[5] >> 1);
430 ext += (short) (scr[4] & 0x03) * 128;
431
432 return ext;
433}
434#endif
435
436
437static void init_ps(ps_packet *p)
438{
439 p->stuff_length=0xF8;
440 p->sheader.clear();
441 p->audio_bound = 0;
442 p->video_bound = 0;
443 p->npes = 0;
444}
445
446static void kill_ps(ps_packet *p)
447{
448 init_ps(p);
449}
450
452{
453 auto *ll = (short *) p->sheader_llength;
454 p->sheader.resize(ntohs(*ll) - 6);
455}
456
457static void setl_ps(ps_packet *p)
458{
460}
461
462
463static int cwrite_ps(uint8_t *buf, ps_packet *p, uint32_t length)
464{
465 (void)length;
466 std::array<uint8_t,4> headr1 {0x00, 0x00, 0x01, PACK_START };
467 std::array<uint8_t,4> headr2 {0x00, 0x00, 0x01, SYS_START };
468 uint8_t buffy = 0xFF;
469
470
471 memcpy(buf,headr1.data(),4);
472 long count = 4;
473 memcpy(buf+count,p->scr,6);
474 count += 6;
475 memcpy(buf+count,p->mux_rate,3);
476 count += 3;
477 memcpy(buf+count,&p->stuff_length,1);
478 count++;
479 for (long i=0; i< (p->stuff_length & 3); i++){
480 memcpy(buf+count,&buffy,1);
481 count++;
482 }
483
484 if (!p->sheader.empty()){
485 memcpy(buf+count,headr2.data(),4);
486 count += 4;
487 memcpy(buf+count,p->sheader_llength,2);
488 count += 2;
489 memcpy(buf+count,p->rate_bound,3);
490 count += 3;
491 memcpy(buf+count,&p->audio_bound,1);
492 count++;
493 memcpy(buf+count,&p->video_bound,1);
494 count++;
495 memcpy(buf+count,&p->reserved,1);
496 count++;
497 memcpy(buf+count,p->sheader.data(),p->sheader.size());
498 count += p->sheader.size();
499 }
500
501 return count;
502}
503
504
505
506static int write_ps_header(uint8_t *buf,
507 uint64_t SCR,
508 uint32_t muxr,
509 uint8_t audio_bound,
510 uint8_t fixed,
511 uint8_t CSPS,
512 uint8_t audio_lock,
513 uint8_t video_lock,
514 uint8_t video_bound,
515 uint8_t navpack)
516{
517 ps_packet p {};
518
519 init_ps(&p);
520
521 uint32_t lscr = htonl((uint32_t) ((SCR/300ULL) & 0x00000000FFFFFFFF));
522 auto *scr = (uint8_t *) &lscr;
523 auto scr_ext = (uint16_t) ((SCR%300ULL) & 0x00000000000001FF);
524
525// SCR = 0
526 p.scr[0] = 0x44;
527 p.scr[1] = 0x00;
528 p.scr[2] = 0x04;
529 p.scr[3] = 0x00;
530 p.scr[4] = 0x04;
531 p.scr[5] = 0x01;
532
533 p.scr[0] = 0x44 | ((scr[0] >> 3)&0x18) | ((scr[0] >> 4)&0x03);
534 p.scr[1] = 0x00 | ((scr[0] << 4)&0xF0) | ((scr[1] >> 4)&0x0F);
535 p.scr[2] = 0x04 | ((scr[1] << 4)&0xF0) | ((scr[2] >> 4)&0x08)
536 | ((scr[2] >> 5)&0x03);
537 p.scr[3] = 0x00 | ((scr[2] << 3)&0xF8) | ((scr[3] >> 5)&0x07);
538 p.scr[4] = 0x04 | ((scr[3] << 3)&0xF8) | ((scr_ext >> 7)&0x03);
539 p.scr[5] = 0x01 | ((scr_ext << 1)&0xFF);
540
541
542 muxr = muxr/50;
543 p.mux_rate[0] = (uint8_t)(muxr >> 14);
544 p.mux_rate[1] = (uint8_t)(0xff & (muxr >> 6));
545 p.mux_rate[2] = (uint8_t)(0x03 | ((muxr & 0x3f) << 2));
546
547 p.stuff_length = 0xF8;
548
549 if (navpack){
550 p.sheader_llength[0] = 0x00;
551 p.sheader_llength[1] = 0x12;
552
553 setl_ps(&p);
554
555 p.rate_bound[0] = (uint8_t)(0x80 | (muxr >>15));
556 p.rate_bound[1] = (uint8_t)(0xff & (muxr >> 7));
557 p.rate_bound[2] = (uint8_t)(0x01 | ((muxr & 0x7f)<<1));
558
559
560 p.audio_bound = (uint8_t)((audio_bound << 2)|(fixed << 1)|CSPS);
561 p.video_bound = (uint8_t)((audio_lock << 7)|
562 (video_lock << 6)|0x20|video_bound);
563 p.reserved = (uint8_t)(0xFF >> 1);
564
565 p.sheader[0] = 0xB9;
566 p.sheader[1] = 0xE0;
567 p.sheader[2] = 0xE8;
568 p.sheader[3] = 0xB8;
569 p.sheader[4] = 0xC0;
570 p.sheader[5] = 0x20;
571 p.sheader[6] = 0xbd;
572 p.sheader[7] = 0xe0;
573 p.sheader[8] = 0x3a;
574 p.sheader[9] = 0xBF;
575 p.sheader[10] = 0xE0;
576 p.sheader[11] = 0x02;
577
578 cwrite_ps(buf, &p, PS_HEADER_L2);
579 kill_ps(&p);
580 return PS_HEADER_L2;
581 }
582 cwrite_ps(buf, &p, PS_HEADER_L1);
583 kill_ps(&p);
584 return PS_HEADER_L1;
585}
586
587using pts_arr = std::array<uint8_t,5>;
588
589static void get_pespts(const uint8_t *spts, pts_arr &pts)
590{
591 //Make sure to set the 1st 4 bits properly
592 pts[0] = 0x01 |
593 ((spts[0] & 0xC0) >>5);
594 pts[1] = ((spts[0] & 0x3F) << 2) |
595 ((spts[1] & 0xC0) >> 6);
596 pts[2] = 0x01 | ((spts[1] & 0x3F) << 2) |
597 ((spts[2] & 0x80) >> 6);
598 pts[3] = ((spts[2] & 0x7F) << 1) |
599 ((spts[3] & 0x80) >> 7);
600 pts[4] = 0x01 | ((spts[3] & 0x7F) << 1);
601}
602
603int write_pes_header(uint8_t id, int length , uint64_t PTS, uint64_t DTS,
604 uint8_t *obuf, int stuffing, uint8_t ptsdts)
605{
606 std::array<uint8_t,2> le {};
607 std::array<uint8_t,3> dummy {};
608 pts_arr ppts {};
609 pts_arr pdts {};
610 std::array<uint8_t,3> headr {0x00, 0x00, 0x01};
611
612 uint32_t lpts = htonl((PTS/300ULL) & 0x00000000FFFFFFFFULL);
613 auto *pts = (uint8_t *) &lpts;
614 get_pespts(pts,ppts);
615 if ((PTS/300ULL) & 0x0000000100000000ULL) ppts[0] |= 0x80;
616
617 uint32_t ldts = htonl((DTS/300ULL) & 0x00000000FFFFFFFFULL);
618 auto *dts = (uint8_t *) &ldts;
619 get_pespts(dts,pdts);
620 if ((DTS/300ULL) & 0x0000000100000000ULL) pdts[0] |= 0x80;
621
622 int c = 0;
623 memcpy(obuf+c,headr.data(),3);
624 c += 3;
625 memcpy(obuf+c,&id,1);
626 c++;
627
628 le[0] = 0;
629 le[1] = 0;
630 length -= 6;
631
632 le[0] |= ((uint8_t)(length >> 8) & 0xFF);
633 le[1] |= ((uint8_t)(length) & 0xFF);
634 memcpy(obuf+c,le.data(),2);
635 c += 2;
636
637 if (id == PADDING_STREAM){
638 memset(obuf+c,0xff,length);
639 c+= length;
640 return c;
641 }
642
643 dummy[0] = 0x80;
644 dummy[1] = 0;
645 dummy[2] = stuffing;
646
647 if (ptsdts == PTS_ONLY){
648 dummy[2] += 5;
649 dummy[1] |= PTS_ONLY;
650 ppts[0] |= 0x20;
651 } else if (ptsdts == PTS_DTS){
652 dummy[2] += 10;
653 dummy[1] |= PTS_DTS;
654 ppts[0] |= 0x30;
655 pdts[0] |= 0x10;
656 }
657
658
659 memcpy(obuf+c,dummy.data(),3);
660 c += 3;
661
662 if (ptsdts == PTS_ONLY){
663 memcpy(obuf+c,ppts.data(),5);
664 c += 5;
665 } else if ( ptsdts == PTS_DTS ){
666 memcpy(obuf+c,ppts.data(),5);
667 c += 5;
668 memcpy(obuf+c,pdts.data(),5);
669 c += 5;
670 }
671
672 memset(obuf+c,0xFF,stuffing);
673 c += stuffing;
674
675 return c;
676}
677
678void write_padding_pes( int pack_size, int extcnt,
679 uint64_t SCR, uint64_t muxr, uint8_t *buf)
680{
681 int pos = 0;
682
683 pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1, 1,
684 0);
685
686 write_pes_header( PADDING_STREAM, pack_size-pos, 0, 0, buf+pos, 0, 0);
687
688}
689
690int write_video_pes( int pack_size, int extcnt, uint64_t vpts,
691 uint64_t vdts, uint64_t SCR, uint64_t muxr,
692 uint8_t *buf, int *vlength,
693 uint8_t ptsdts, ringbuffer *vrbuffer)
694{
695 int stuff = 0;
696 int length = *vlength;
697
698 if (! length) return 0;
700
701 if ( ptsdts == PTS_ONLY){
702 p += 5;
703 } else if (ptsdts == PTS_DTS){
704 p += 10;
705 }
706
707 if ( length+p >= pack_size){
708 length = pack_size;
709 } else {
710 if (pack_size - length - p <= PES_MIN){
711 stuff = pack_size - length-p;
712 length = pack_size;
713 } else {
714 length = length+p;
715 }
716 }
717
718 int pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1,
719 1, 0);
720
721 pos += write_pes_header( 0xE0, length-pos, vpts, vdts, buf+pos,
722 stuff, ptsdts);
723 if (length-pos > *vlength){
724 LOG(VB_GENERAL, LOG_ERR,
725 QString("WHAT THE HELL %1 > %2").arg(length-pos).arg(*vlength));
726 }
727
728 int add = ring_read( vrbuffer, buf+pos, length-pos);
729 *vlength = add;
730 if (add < 0) return -1;
731 pos += add;
732
733 if (pos+PES_MIN < pack_size){
734 write_pes_header( PADDING_STREAM, pack_size-pos, 0, 0,
735 buf+pos, 0, 0);
736 pos = pack_size;
737 }
738 return pos;
739}
740
741int write_audio_pes( int pack_size, int extcnt, int n, uint64_t pts,
742 uint64_t SCR, uint32_t muxr, uint8_t *buf, int *alength,
743 uint8_t ptsdts, ringbuffer *arbuffer)
744{
745 int stuff = 0;
746 int length = *alength;
747
748 if (!length) return 0;
750
751 if (ptsdts == PTS_ONLY){
752 p += 5;
753 }
754
755 if ( length+p >= pack_size){
756 length = pack_size;
757 } else {
758 if (pack_size-length-p <= PES_MIN){
759 stuff = pack_size - length-p;
760 length = pack_size;
761 } else {
762 length = length+p;
763 }
764 }
765 int pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1,
766 1, 0);
767 pos += write_pes_header( 0xC0+n, length-pos, pts, 0, buf+pos, stuff,
768 ptsdts);
769 int add = ring_read( arbuffer, buf+pos, length-pos);
770 *alength = add;
771 if (add < 0) return -1;
772 pos += add;
773
774 if (pos+PES_MIN < pack_size){
775 write_pes_header( PADDING_STREAM, pack_size-pos, 0,0,
776 buf+pos, 0, 0);
777 pos = pack_size;
778 }
779 if (pos != pack_size) {
780 LOG(VB_GENERAL, LOG_ERR, QString("apos: %1").arg(pos));
781 exit(1);
782 }
783
784 return pos;
785}
786
787int write_ac3_pes( int pack_size, int extcnt, int n,
788 uint64_t pts, uint64_t SCR,
789 uint32_t muxr, uint8_t *buf, int *alength, uint8_t ptsdts,
790 int nframes,int ac3_off, ringbuffer *ac3rbuffer)
791{
792 int stuff = 0;
793 int length = *alength;
794
795 if (!length) return 0;
796 int p = PS_HEADER_L1+PES_H_MIN+4;
797
798 if (ptsdts == PTS_ONLY){
799 p += 5;
800 }
801
802 if ( length+p >= pack_size){
803 length = pack_size;
804 } else {
805 if (pack_size-length-p <= PES_MIN){
806 stuff = pack_size - length-p;
807 length = pack_size;
808 } else {
809 length = length+p;
810 }
811 }
812 int pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1,
813 1, 0);
814
815 pos += write_pes_header( PRIVATE_STREAM1, length-pos, pts, 0,
816 buf+pos, stuff, ptsdts);
817 buf[pos] = 0x80 + n;
818 buf[pos+1] = nframes;
819 buf[pos+2] = (ac3_off >> 8)& 0xFF;
820 buf[pos+3] = (ac3_off)& 0xFF;
821 pos += 4;
822
823 int add = ring_read( ac3rbuffer, buf+pos, length-pos);
824 *alength = add;
825 if (add < 0) return -1;
826 pos += add;
827
828 if (pos+PES_MIN < pack_size){
829 write_pes_header( PADDING_STREAM, pack_size-pos, 0,0,
830 buf+pos, 0, 0);
831 pos = pack_size;
832 }
833 if (pos != pack_size) {
834 LOG(VB_GENERAL, LOG_ERR, QString("apos: %1").arg(pos));
835 exit(1);
836 }
837
838 return pos;
839}
840
841int write_nav_pack(int pack_size, int extcnt, uint64_t SCR, uint32_t muxr,
842 uint8_t *buf)
843{
844 int pos = 0;
845 std::array<uint8_t,5> headr {0x00, 0x00, 0x01, PRIVATE_STREAM2, 0x03 };
846 (void)pack_size;
847
848 pos = write_ps_header( buf, SCR, muxr, extcnt, 0, 0, 1, 1, 1, 1);
849 memcpy(buf+pos, headr.data(), 5);
850 buf[pos+5] = 0xD4;
851 pos += 6;
852 memset(buf+pos, 0, 0x03d4);
853 pos += 0x03d4;
854
855 memcpy(buf+pos, headr.data(), 5);
856 buf[pos+5] = 0xFA;
857 pos += 6;
858 memset(buf+pos, 0, 0x03fA);
859 pos += 0x03fA;
860
861 return pos;
862}
unsigned short uint16_t
Definition: iso6937tables.h:3
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
Definition: mythchrono.h:44
int write_pes_header(uint8_t id, int length, uint64_t PTS, uint64_t DTS, uint8_t *obuf, int stuffing, uint8_t ptsdts)
Definition: pes.cpp:603
void get_pes(pes_in_t *p, uint8_t *buf, int count, void(*func)(pes_in_t *p))
Definition: pes.cpp:166
static void setl_ps(ps_packet *p)
Definition: pes.cpp:457
static void init_ps(ps_packet *p)
Definition: pes.cpp:437
static void setlength_ps(ps_packet *p)
Definition: pes.cpp:451
static int write_ps_header(uint8_t *buf, uint64_t SCR, uint32_t muxr, uint8_t audio_bound, uint8_t fixed, uint8_t CSPS, uint8_t audio_lock, uint8_t video_lock, uint8_t video_bound, uint8_t navpack)
Definition: pes.cpp:506
void write_padding_pes(int pack_size, int extcnt, uint64_t SCR, uint64_t muxr, uint8_t *buf)
Definition: pes.cpp:678
static void get_pespts(const uint8_t *spts, pts_arr &pts)
Definition: pes.cpp:589
void printptss(int64_t pts)
Definition: pes.cpp:60
void printpts(int64_t pts)
Definition: pes.cpp:43
int write_audio_pes(int pack_size, int extcnt, int n, uint64_t pts, uint64_t SCR, uint32_t muxr, uint8_t *buf, int *alength, uint8_t ptsdts, ringbuffer *arbuffer)
Definition: pes.cpp:741
int ptscmp(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:114
static void kill_ps(ps_packet *p)
Definition: pes.cpp:446
std::array< uint8_t, 5 > pts_arr
Definition: pes.cpp:587
int write_video_pes(int pack_size, int extcnt, uint64_t vpts, uint64_t vdts, uint64_t SCR, uint64_t muxr, uint8_t *buf, int *vlength, uint8_t ptsdts, ringbuffer *vrbuffer)
Definition: pes.cpp:690
uint64_t ptsadd(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:140
int64_t ptsdiff(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:78
int write_nav_pack(int pack_size, int extcnt, uint64_t SCR, uint32_t muxr, uint8_t *buf)
Definition: pes.cpp:841
static int cwrite_ps(uint8_t *buf, ps_packet *p, uint32_t length)
Definition: pes.cpp:463
int write_ac3_pes(int pack_size, int extcnt, int n, uint64_t pts, uint64_t SCR, uint32_t muxr, uint8_t *buf, int *alength, uint8_t ptsdts, int nframes, int ac3_off, ringbuffer *ac3rbuffer)
Definition: pes.cpp:787
uint64_t uptsdiff(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:104
void init_pes_in(pes_in_t *p, int t, ringbuffer *rb, int wi)
Definition: pes.cpp:147
#define AUDIO_STREAM_S
Definition: pes.h:26
#define PTS_ONLY
Definition: pes.h:46
#define PS_HEADER_L1
Definition: pes.h:13
#define VIDEO_STREAM_E
Definition: pes.h:29
#define MMAX_PLENGTH
Definition: pes.h:50
#define PRIVATE_STREAM1
Definition: pes.h:23
#define ISO13522_STREAM
Definition: pes.h:33
#define AUDIO_STREAM_E
Definition: pes.h:27
#define ECM_STREAM
Definition: pes.h:30
#define PROG_STREAM_DIR
Definition: pes.h:34
#define PROG_STREAM_MAP
Definition: pes.h:22
#define PTS_DTS
Definition: pes.h:47
#define EMM_STREAM
Definition: pes.h:31
#define PADDING_STREAM
Definition: pes.h:24
#define SYS_START
Definition: pes.h:21
#define PES_H_MIN
Definition: pes.h:16
#define DSM_CC_STREAM
Definition: pes.h:32
#define MAX_PLENGTH
Definition: pes.h:49
#define VIDEO_STREAM_S
Definition: pes.h:28
#define PACK_START
Definition: pes.h:20
#define PS_HEADER_L2
Definition: pes.h:14
#define MAX_PTS2
Definition: pes.h:53
#define PRIVATE_STREAM2
Definition: pes.h:25
#define MAX_PTS
Definition: pes.h:52
#define PES_MIN
Definition: pes.h:15
static void ptsinc(uint64_t *pts1, uint64_t pts2)
Definition: pes.h:127
int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:200
int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:90
static int ring_wpos(ringbuffer *rbuf)
Definition: ringbuffer.h:77
Definition: pes.h:70
Definition: pes.h:55