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){
155 p->buf = static_cast<uchar*>(malloc(MAX_PLENGTH*sizeof(uint8_t)));
156 memset(p->buf,0,MAX_PLENGTH*sizeof(uint8_t));
157 } else if (rb) {
158 p->rbuf = rb;
159 }
160 if (p->rbuf) p->ini_pos = ring_wpos(p->rbuf);
161 p->done = false;
162 memset(p->pts, 0 , 5);
163 memset(p->dts, 0 , 5);
164}
165
166
167void get_pes (pes_in_t *p, uint8_t *buf, int count, void (*func)(pes_in_t *p))
168{
169 unsigned short *pl = nullptr;
170 bool done = false;
171
172 std::array<uint8_t,3> headr { 0x00, 0x00, 0x01} ;
173 while (!done)
174 {
175 int c=0;
176 done = true;
177 while (c < count && (!p->mpeg ||
178 (p->mpeg == 2 && p->found < 9))
179 && (p->found < 5 || !p->done)){
180 switch ( p->found ){
181 case 0:
182 case 1:
183 if (buf[c] == 0x00) p->found++;
184 else p->found = 0;
185 c++;
186 break;
187 case 2:
188 if (buf[c] == 0x01) p->found++;
189 else if (buf[c] == 0){
190 p->found = 2;
191 } else {
192 p->found = 0;
193 }
194 c++;
195 break;
196 case 3:
197 p->cid = 0;
198 switch (buf[c]){
199 case PROG_STREAM_MAP:
200 case PRIVATE_STREAM2:
201 case PROG_STREAM_DIR:
202 case ECM_STREAM :
203 case EMM_STREAM :
204 case PADDING_STREAM :
205 case DSM_CC_STREAM :
206 case ISO13522_STREAM:
207 p->done = true;
208 [[fallthrough]];
209 case PRIVATE_STREAM1:
212 p->found++;
213 p->cid = buf[c];
214 c++;
215 break;
216 default:
217 case PACK_START:
218 case SYS_START:
219 p->found = 0;
220 c++;
221 break;
222 }
223 break;
224
225
226 case 4:
227 if (count-c > 1){
228 pl = (unsigned short *) (buf+c);
229 p->plength = ntohs(*pl);
230 p->plen[0] = buf[c];
231 c++;
232 p->plen[1] = buf[c];
233 c++;
234 p->found+=2;
235 } else {
236 p->plen[0] = buf[c];
237 p->found++;
238 return;
239 }
240 break;
241 case 5:
242 p->plen[1] = buf[c];
243 c++;
244 pl = (unsigned short *) p->plen;
245 p->plength = ntohs(*pl);
246 p->found++;
247 break;
248
249
250 case 6:
251 if (!p->done){
252 p->flag1 = buf[c];
253 c++;
254 p->found++;
255 if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2;
256 else {
257 LOG(VB_GENERAL, LOG_ERR,
258 "Error: THIS IS AN MPEG1 FILE");
259 exit(1);
260 }
261 }
262 break;
263
264 case 7:
265 if ( !p->done && p->mpeg == 2){
266 p->flag2 = buf[c];
267 c++;
268 p->found++;
269 }
270 break;
271
272 case 8:
273 if ( !p->done && p->mpeg == 2){
274 p->hlength = buf[c];
275 c++;
276 p->found++;
277 }
278 break;
279
280 default:
281
282 break;
283 }
284 }
285
286 if (!p->plength) p->plength = MMAX_PLENGTH-6;
287
288
289 if ( p->done || (p->mpeg == 2 && p->found >= 9) ){
290 switch (p->cid){
291
294 case PRIVATE_STREAM1:
295
296 if (p->withbuf){
297 memcpy(p->buf, headr.data(), 3);
298 p->buf[3] = p->cid;
299 memcpy(p->buf+4,p->plen,2);
300 } else {
301 memcpy(p->hbuf, headr.data(), 3);
302 p->hbuf[3] = p->cid;
303 memcpy(p->hbuf+4,p->plen,2);
304 }
305
306 if (p->found == 9){
307 if (p->withbuf){
308 p->buf[6] = p->flag1;
309 p->buf[7] = p->flag2;
310 p->buf[8] = p->hlength;
311 } else {
312 p->hbuf[6] = p->flag1;
313 p->hbuf[7] = p->flag2;
314 p->hbuf[8] = p->hlength;
315 }
316 }
317
318 if ( (p->flag2 & PTS_ONLY) && p->found >= 9 && p->found < 14){
319 while (c < count && p->found < 14){
320 p->pts[p->found-9] = buf[c];
321 if (p->withbuf)
322 p->buf[p->found] = buf[c];
323 else
324 p->hbuf[p->found] = buf[c];
325 c++;
326 p->found++;
327 }
328 if (c == count) return;
329 }
330
331 if (((p->flag2 & PTS_DTS) == 0xC0) && p->found >= 14 && p->found < 19){
332 while (c < count && p->found < 19){
333 p->dts[p->found-14] = buf[c];
334 if (p->withbuf)
335 p->buf[p->found] = buf[c];
336 else
337 p->hbuf[p->found] = buf[c];
338 c++;
339 p->found++;
340 }
341 if (c == count) return;
342 }
343
344
345 while (c < count && p->found < p->plength+6){
346 int l = count -c;
347 if (l+p->found > p->plength+6)
348 l = p->plength+6-p->found;
349 if (p->withbuf)
350 memcpy(p->buf+p->found, buf+c, l);
351 else {
352 if ( p->found <
353 (unsigned int)p->hlength+9 ){
354 int rest = p->hlength+9-p->found;
355 memcpy(p->hbuf+p->found, buf+c, rest);
356 if (ring_write(p->rbuf, buf+c+rest,
357 l-rest) <0){
358 exit(1);
359 }
360 } else {
361 if (ring_write(p->rbuf, buf+c, l)<0){
362 LOG(VB_GENERAL, LOG_ERR,
363 QString("ring buffer overflow %1")
364 .arg(p->rbuf->size));
365 exit(1);
366 }
367 }
368 }
369
370 p->found += l;
371 c += l;
372 }
373 if(p->found == p->plength+6){
374 func(p);
375 }
376 break;
377 }
378
379 if ( p->done ){
380 if( p->found + count - c < p->plength+6){
381 p->found += count-c;
382 c = count;
383 } else {
384 c += p->plength+6 - p->found;
385 p->found = p->plength+6;
386 }
387 }
388
389 if (p->plength && p->found == p->plength+6) {
390 init_pes_in(p, p->type, nullptr, p->withbuf);
391 if (c < count) {
392 done = false;
393 count -= c;
394 buf += c;
395 }
396 }
397 }
398 }
399}
400
401
402#if 0
403static uint32_t scr_base_ps(const uint8_t *scr)
404{
405 uint32_t base = 0;
406 uint8_t *buf = (uint8_t *)&base;
407
408 buf[0] |= (uint8_t)((scr[0] & 0x18) << 3);
409 buf[0] |= (uint8_t)((scr[0] & 0x03) << 4);
410 buf[0] |= (uint8_t)((scr[1] & 0xF0) >> 4);
411
412 buf[1] |= (uint8_t)((scr[1] & 0x0F) << 4);
413 buf[1] |= (uint8_t)((scr[2] & 0xF0) >> 4);
414
415 buf[2] |= (uint8_t)((scr[2] & 0x08) << 4);
416 buf[2] |= (uint8_t)((scr[2] & 0x03) << 5);
417 buf[2] |= (uint8_t)((scr[3] & 0xF8) >> 3);
418
419 buf[3] |= (uint8_t)((scr[3] & 0x07) << 5);
420 buf[3] |= (uint8_t)((scr[4] & 0xF8) >> 3);
421
422 base = ntohl(base);
423 return base;
424}
425
426static uint16_t scr_ext_ps(const uint8_t *scr)
427{
428 short ext = 0;
429
430 ext = (short)(scr[5] >> 1);
431 ext += (short) (scr[4] & 0x03) * 128;
432
433 return ext;
434}
435#endif
436
437
438static void init_ps(ps_packet *p)
439{
440 p->stuff_length=0xF8;
441 p->data = nullptr;
442 p->sheader_length = 0;
443 p->audio_bound = 0;
444 p->video_bound = 0;
445 p->npes = 0;
446}
447
448static void kill_ps(ps_packet *p)
449{
450 if (p->data)
451 free(p->data);
452 init_ps(p);
453}
454
456{
457 auto *ll = (short *) p->sheader_llength;
458 p->sheader_length = ntohs(*ll) - 6;
459}
460
461static void setl_ps(ps_packet *p)
462{
464 p->data = (uint8_t *) malloc(p->sheader_length);
465}
466
467
468static int cwrite_ps(uint8_t *buf, ps_packet *p, uint32_t length)
469{
470 (void)length;
471 std::array<uint8_t,4> headr1 {0x00, 0x00, 0x01, PACK_START };
472 std::array<uint8_t,4> headr2 {0x00, 0x00, 0x01, SYS_START };
473 uint8_t buffy = 0xFF;
474
475
476 memcpy(buf,headr1.data(),4);
477 long count = 4;
478 memcpy(buf+count,p->scr,6);
479 count += 6;
480 memcpy(buf+count,p->mux_rate,3);
481 count += 3;
482 memcpy(buf+count,&p->stuff_length,1);
483 count++;
484 for (long i=0; i< (p->stuff_length & 3); i++){
485 memcpy(buf+count,&buffy,1);
486 count++;
487 }
488
489 if (p->sheader_length){
490 memcpy(buf+count,headr2.data(),4);
491 count += 4;
492 memcpy(buf+count,p->sheader_llength,2);
493 count += 2;
494 memcpy(buf+count,p->rate_bound,3);
495 count += 3;
496 memcpy(buf+count,&p->audio_bound,1);
497 count++;
498 memcpy(buf+count,&p->video_bound,1);
499 count++;
500 memcpy(buf+count,&p->reserved,1);
501 count++;
502 memcpy(buf+count,p->data,p->sheader_length);
503 count += p->sheader_length;
504 }
505
506 return count;
507}
508
509
510
511static int write_ps_header(uint8_t *buf,
512 uint64_t SCR,
513 uint32_t muxr,
514 uint8_t audio_bound,
515 uint8_t fixed,
516 uint8_t CSPS,
517 uint8_t audio_lock,
518 uint8_t video_lock,
519 uint8_t video_bound,
520 uint8_t navpack)
521{
522 ps_packet p {};
523
524 init_ps(&p);
525
526 uint32_t lscr = htonl((uint32_t) ((SCR/300ULL) & 0x00000000FFFFFFFF));
527 auto *scr = (uint8_t *) &lscr;
528 auto scr_ext = (uint16_t) ((SCR%300ULL) & 0x00000000000001FF);
529
530// SCR = 0
531 p.scr[0] = 0x44;
532 p.scr[1] = 0x00;
533 p.scr[2] = 0x04;
534 p.scr[3] = 0x00;
535 p.scr[4] = 0x04;
536 p.scr[5] = 0x01;
537
538 p.scr[0] = 0x44 | ((scr[0] >> 3)&0x18) | ((scr[0] >> 4)&0x03);
539 p.scr[1] = 0x00 | ((scr[0] << 4)&0xF0) | ((scr[1] >> 4)&0x0F);
540 p.scr[2] = 0x04 | ((scr[1] << 4)&0xF0) | ((scr[2] >> 4)&0x08)
541 | ((scr[2] >> 5)&0x03);
542 p.scr[3] = 0x00 | ((scr[2] << 3)&0xF8) | ((scr[3] >> 5)&0x07);
543 p.scr[4] = 0x04 | ((scr[3] << 3)&0xF8) | ((scr_ext >> 7)&0x03);
544 p.scr[5] = 0x01 | ((scr_ext << 1)&0xFF);
545
546
547 muxr = muxr/50;
548 p.mux_rate[0] = (uint8_t)(muxr >> 14);
549 p.mux_rate[1] = (uint8_t)(0xff & (muxr >> 6));
550 p.mux_rate[2] = (uint8_t)(0x03 | ((muxr & 0x3f) << 2));
551
552 p.stuff_length = 0xF8;
553
554 if (navpack){
555 p.sheader_llength[0] = 0x00;
556 p.sheader_llength[1] = 0x12;
557
558 setl_ps(&p);
559
560 p.rate_bound[0] = (uint8_t)(0x80 | (muxr >>15));
561 p.rate_bound[1] = (uint8_t)(0xff & (muxr >> 7));
562 p.rate_bound[2] = (uint8_t)(0x01 | ((muxr & 0x7f)<<1));
563
564
565 p.audio_bound = (uint8_t)((audio_bound << 2)|(fixed << 1)|CSPS);
566 p.video_bound = (uint8_t)((audio_lock << 7)|
567 (video_lock << 6)|0x20|video_bound);
568 p.reserved = (uint8_t)(0xFF >> 1);
569
570 // The above setl_ps call causes a 0x12 byte data area
571 // to be allocated.
572 // NOLINTBEGIN(clang-analyzer-security.ArrayBound)
573 p.data[0] = 0xB9;
574 p.data[1] = 0xE0;
575 p.data[2] = 0xE8;
576 p.data[3] = 0xB8;
577 p.data[4] = 0xC0;
578 p.data[5] = 0x20;
579 p.data[6] = 0xbd;
580 p.data[7] = 0xe0;
581 p.data[8] = 0x3a;
582 p.data[9] = 0xBF;
583 p.data[10] = 0xE0;
584 p.data[11] = 0x02;
585 // NOLINTEND(clang-analyzer-security.ArrayBound)
586
587 cwrite_ps(buf, &p, PS_HEADER_L2);
588 kill_ps(&p);
589 return PS_HEADER_L2;
590 }
591 cwrite_ps(buf, &p, PS_HEADER_L1);
592 kill_ps(&p);
593 return PS_HEADER_L1;
594}
595
596using pts_arr = std::array<uint8_t,5>;
597
598static void get_pespts(const uint8_t *spts, pts_arr &pts)
599{
600 //Make sure to set the 1st 4 bits properly
601 pts[0] = 0x01 |
602 ((spts[0] & 0xC0) >>5);
603 pts[1] = ((spts[0] & 0x3F) << 2) |
604 ((spts[1] & 0xC0) >> 6);
605 pts[2] = 0x01 | ((spts[1] & 0x3F) << 2) |
606 ((spts[2] & 0x80) >> 6);
607 pts[3] = ((spts[2] & 0x7F) << 1) |
608 ((spts[3] & 0x80) >> 7);
609 pts[4] = 0x01 | ((spts[3] & 0x7F) << 1);
610}
611
612int write_pes_header(uint8_t id, int length , uint64_t PTS, uint64_t DTS,
613 uint8_t *obuf, int stuffing, uint8_t ptsdts)
614{
615 std::array<uint8_t,2> le {};
616 std::array<uint8_t,3> dummy {};
617 pts_arr ppts {};
618 pts_arr pdts {};
619 std::array<uint8_t,3> headr {0x00, 0x00, 0x01};
620
621 uint32_t lpts = htonl((PTS/300ULL) & 0x00000000FFFFFFFFULL);
622 auto *pts = (uint8_t *) &lpts;
623 get_pespts(pts,ppts);
624 if ((PTS/300ULL) & 0x0000000100000000ULL) ppts[0] |= 0x80;
625
626 uint32_t ldts = htonl((DTS/300ULL) & 0x00000000FFFFFFFFULL);
627 auto *dts = (uint8_t *) &ldts;
628 get_pespts(dts,pdts);
629 if ((DTS/300ULL) & 0x0000000100000000ULL) pdts[0] |= 0x80;
630
631 int c = 0;
632 memcpy(obuf+c,headr.data(),3);
633 c += 3;
634 memcpy(obuf+c,&id,1);
635 c++;
636
637 le[0] = 0;
638 le[1] = 0;
639 length -= 6;
640
641 le[0] |= ((uint8_t)(length >> 8) & 0xFF);
642 le[1] |= ((uint8_t)(length) & 0xFF);
643 memcpy(obuf+c,le.data(),2);
644 c += 2;
645
646 if (id == PADDING_STREAM){
647 memset(obuf+c,0xff,length);
648 c+= length;
649 return c;
650 }
651
652 dummy[0] = 0x80;
653 dummy[1] = 0;
654 dummy[2] = stuffing;
655
656 if (ptsdts == PTS_ONLY){
657 dummy[2] += 5;
658 dummy[1] |= PTS_ONLY;
659 ppts[0] |= 0x20;
660 } else if (ptsdts == PTS_DTS){
661 dummy[2] += 10;
662 dummy[1] |= PTS_DTS;
663 ppts[0] |= 0x30;
664 pdts[0] |= 0x10;
665 }
666
667
668 memcpy(obuf+c,dummy.data(),3);
669 c += 3;
670
671 if (ptsdts == PTS_ONLY){
672 memcpy(obuf+c,ppts.data(),5);
673 c += 5;
674 } else if ( ptsdts == PTS_DTS ){
675 memcpy(obuf+c,ppts.data(),5);
676 c += 5;
677 memcpy(obuf+c,pdts.data(),5);
678 c += 5;
679 }
680
681 memset(obuf+c,0xFF,stuffing);
682 c += stuffing;
683
684 return c;
685}
686
687void write_padding_pes( int pack_size, int extcnt,
688 uint64_t SCR, uint64_t muxr, uint8_t *buf)
689{
690 int pos = 0;
691
692 pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1, 1,
693 0);
694
695 write_pes_header( PADDING_STREAM, pack_size-pos, 0, 0, buf+pos, 0, 0);
696
697}
698
699int write_video_pes( int pack_size, int extcnt, uint64_t vpts,
700 uint64_t vdts, uint64_t SCR, uint64_t muxr,
701 uint8_t *buf, int *vlength,
702 uint8_t ptsdts, ringbuffer *vrbuffer)
703{
704 int stuff = 0;
705 int length = *vlength;
706
707 if (! length) return 0;
709
710 if ( ptsdts == PTS_ONLY){
711 p += 5;
712 } else if (ptsdts == PTS_DTS){
713 p += 10;
714 }
715
716 if ( length+p >= pack_size){
717 length = pack_size;
718 } else {
719 if (pack_size - length - p <= PES_MIN){
720 stuff = pack_size - length-p;
721 length = pack_size;
722 } else {
723 length = length+p;
724 }
725 }
726
727 int pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1,
728 1, 0);
729
730 pos += write_pes_header( 0xE0, length-pos, vpts, vdts, buf+pos,
731 stuff, ptsdts);
732 if (length-pos > *vlength){
733 LOG(VB_GENERAL, LOG_ERR,
734 QString("WHAT THE HELL %1 > %2").arg(length-pos).arg(*vlength));
735 }
736
737 int add = ring_read( vrbuffer, buf+pos, length-pos);
738 *vlength = add;
739 if (add < 0) return -1;
740 pos += add;
741
742 if (pos+PES_MIN < pack_size){
743 write_pes_header( PADDING_STREAM, pack_size-pos, 0, 0,
744 buf+pos, 0, 0);
745 pos = pack_size;
746 }
747 return pos;
748}
749
750int write_audio_pes( int pack_size, int extcnt, int n, uint64_t pts,
751 uint64_t SCR, uint32_t muxr, uint8_t *buf, int *alength,
752 uint8_t ptsdts, ringbuffer *arbuffer)
753{
754 int stuff = 0;
755 int length = *alength;
756
757 if (!length) return 0;
759
760 if (ptsdts == PTS_ONLY){
761 p += 5;
762 }
763
764 if ( length+p >= pack_size){
765 length = pack_size;
766 } else {
767 if (pack_size-length-p <= PES_MIN){
768 stuff = pack_size - length-p;
769 length = pack_size;
770 } else {
771 length = length+p;
772 }
773 }
774 int pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1,
775 1, 0);
776 pos += write_pes_header( 0xC0+n, length-pos, pts, 0, buf+pos, stuff,
777 ptsdts);
778 int add = ring_read( arbuffer, buf+pos, length-pos);
779 *alength = add;
780 if (add < 0) return -1;
781 pos += add;
782
783 if (pos+PES_MIN < pack_size){
784 write_pes_header( PADDING_STREAM, pack_size-pos, 0,0,
785 buf+pos, 0, 0);
786 pos = pack_size;
787 }
788 if (pos != pack_size) {
789 LOG(VB_GENERAL, LOG_ERR, QString("apos: %1").arg(pos));
790 exit(1);
791 }
792
793 return pos;
794}
795
796int write_ac3_pes( int pack_size, int extcnt, int n,
797 uint64_t pts, uint64_t SCR,
798 uint32_t muxr, uint8_t *buf, int *alength, uint8_t ptsdts,
799 int nframes,int ac3_off, ringbuffer *ac3rbuffer)
800{
801 int stuff = 0;
802 int length = *alength;
803
804 if (!length) return 0;
805 int p = PS_HEADER_L1+PES_H_MIN+4;
806
807 if (ptsdts == PTS_ONLY){
808 p += 5;
809 }
810
811 if ( length+p >= pack_size){
812 length = pack_size;
813 } else {
814 if (pack_size-length-p <= PES_MIN){
815 stuff = pack_size - length-p;
816 length = pack_size;
817 } else {
818 length = length+p;
819 }
820 }
821 int pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1,
822 1, 0);
823
824 pos += write_pes_header( PRIVATE_STREAM1, length-pos, pts, 0,
825 buf+pos, stuff, ptsdts);
826 buf[pos] = 0x80 + n;
827 buf[pos+1] = nframes;
828 buf[pos+2] = (ac3_off >> 8)& 0xFF;
829 buf[pos+3] = (ac3_off)& 0xFF;
830 pos += 4;
831
832 int add = ring_read( ac3rbuffer, buf+pos, length-pos);
833 *alength = add;
834 if (add < 0) return -1;
835 pos += add;
836
837 if (pos+PES_MIN < pack_size){
838 write_pes_header( PADDING_STREAM, pack_size-pos, 0,0,
839 buf+pos, 0, 0);
840 pos = pack_size;
841 }
842 if (pos != pack_size) {
843 LOG(VB_GENERAL, LOG_ERR, QString("apos: %1").arg(pos));
844 exit(1);
845 }
846
847 return pos;
848}
849
850int write_nav_pack(int pack_size, int extcnt, uint64_t SCR, uint32_t muxr,
851 uint8_t *buf)
852{
853 int pos = 0;
854 std::array<uint8_t,5> headr {0x00, 0x00, 0x01, PRIVATE_STREAM2, 0x03 };
855 (void)pack_size;
856
857 pos = write_ps_header( buf, SCR, muxr, extcnt, 0, 0, 1, 1, 1, 1);
858 memcpy(buf+pos, headr.data(), 5);
859 buf[pos+5] = 0xD4;
860 pos += 6;
861 memset(buf+pos, 0, 0x03d4);
862 pos += 0x03d4;
863
864 memcpy(buf+pos, headr.data(), 5);
865 buf[pos+5] = 0xFA;
866 pos += 6;
867 memset(buf+pos, 0, 0x03fA);
868 pos += 0x03fA;
869
870 return pos;
871}
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:55
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:612
void get_pes(pes_in_t *p, uint8_t *buf, int count, void(*func)(pes_in_t *p))
Definition: pes.cpp:167
static void setl_ps(ps_packet *p)
Definition: pes.cpp:461
static void init_ps(ps_packet *p)
Definition: pes.cpp:438
static void setlength_ps(ps_packet *p)
Definition: pes.cpp:455
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:511
void write_padding_pes(int pack_size, int extcnt, uint64_t SCR, uint64_t muxr, uint8_t *buf)
Definition: pes.cpp:687
static void get_pespts(const uint8_t *spts, pts_arr &pts)
Definition: pes.cpp:598
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:750
int ptscmp(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:114
static void kill_ps(ps_packet *p)
Definition: pes.cpp:448
std::array< uint8_t, 5 > pts_arr
Definition: pes.cpp:596
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:699
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:850
static int cwrite_ps(uint8_t *buf, ps_packet *p, uint32_t length)
Definition: pes.cpp:468
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:796
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:202
int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:92
static int ring_wpos(ringbuffer *rbuf)
Definition: ringbuffer.h:77
Definition: pes.h:70
Definition: pes.h:55