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