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 
43 void 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 
60 void 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 */
78 int64_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 */
104 uint64_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 
114 int 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 
140 uint64_t ptsadd(uint64_t pts1, uint64_t pts2)
141 {
142  ptsinc(&pts1,pts2);
143  return pts1;
144 
145 }
146 
147 void 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 
167 void 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 = true;
171 
172  std::array<uint8_t,3> headr { 0x00, 0x00, 0x01} ;
173  do {
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 
291  case AUDIO_STREAM_S ... AUDIO_STREAM_E:
293  case PRIVATE_STREAM1:
294 
295  if (p->withbuf){
296  memcpy(p->buf, headr.data(), 3);
297  p->buf[3] = p->cid;
298  memcpy(p->buf+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 < 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 < 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+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  } while(!done);
398 }
399 
400 
401 #if 0
402 static 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 
425 static 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 
437 static void init_ps(ps_packet *p)
438 {
439  p->stuff_length=0xF8;
440  p->data = nullptr;
441  p->sheader_length = 0;
442  p->audio_bound = 0;
443  p->video_bound = 0;
444  p->npes = 0;
445 }
446 
447 static void kill_ps(ps_packet *p)
448 {
449  if (p->data)
450  free(p->data);
451  init_ps(p);
452 }
453 
454 static void setlength_ps(ps_packet *p)
455 {
456  auto *ll = (short *) p->sheader_llength;
457  p->sheader_length = ntohs(*ll) - 6;
458 }
459 
460 static void setl_ps(ps_packet *p)
461 {
462  setlength_ps(p);
463  p->data = (uint8_t *) malloc(p->sheader_length);
464 }
465 
466 
467 static int cwrite_ps(uint8_t *buf, ps_packet *p, uint32_t length)
468 {
469  (void)length;
470  std::array<uint8_t,4> headr1 {0x00, 0x00, 0x01, PACK_START };
471  std::array<uint8_t,4> headr2 {0x00, 0x00, 0x01, SYS_START };
472  uint8_t buffy = 0xFF;
473 
474 
475  memcpy(buf,headr1.data(),4);
476  long count = 4;
477  memcpy(buf+count,p->scr,6);
478  count += 6;
479  memcpy(buf+count,p->mux_rate,3);
480  count += 3;
481  memcpy(buf+count,&p->stuff_length,1);
482  count++;
483  for (long i=0; i< (p->stuff_length & 3); i++){
484  memcpy(buf+count,&buffy,1);
485  count++;
486  }
487 
488  if (p->sheader_length){
489  memcpy(buf+count,headr2.data(),4);
490  count += 4;
491  memcpy(buf+count,p->sheader_llength,2);
492  count += 2;
493  memcpy(buf+count,p->rate_bound,3);
494  count += 3;
495  memcpy(buf+count,&p->audio_bound,1);
496  count++;
497  memcpy(buf+count,&p->video_bound,1);
498  count++;
499  memcpy(buf+count,&p->reserved,1);
500  count++;
501  memcpy(buf+count,p->data,p->sheader_length);
502  count += p->sheader_length;
503  }
504 
505  return count;
506 }
507 
508 
509 
510 static int write_ps_header(uint8_t *buf,
511  uint64_t SCR,
512  uint32_t muxr,
513  uint8_t audio_bound,
514  uint8_t fixed,
515  uint8_t CSPS,
516  uint8_t audio_lock,
517  uint8_t video_lock,
518  uint8_t video_bound,
519  uint8_t navpack)
520 {
521  ps_packet p {};
522 
523  init_ps(&p);
524 
525  uint32_t lscr = htonl((uint32_t) ((SCR/300ULL) & 0x00000000FFFFFFFF));
526  auto *scr = (uint8_t *) &lscr;
527  auto scr_ext = (uint16_t) ((SCR%300ULL) & 0x00000000000001FF);
528 
529 // SCR = 0
530  p.scr[0] = 0x44;
531  p.scr[1] = 0x00;
532  p.scr[2] = 0x04;
533  p.scr[3] = 0x00;
534  p.scr[4] = 0x04;
535  p.scr[5] = 0x01;
536 
537  p.scr[0] = 0x44 | ((scr[0] >> 3)&0x18) | ((scr[0] >> 4)&0x03);
538  p.scr[1] = 0x00 | ((scr[0] << 4)&0xF0) | ((scr[1] >> 4)&0x0F);
539  p.scr[2] = 0x04 | ((scr[1] << 4)&0xF0) | ((scr[2] >> 4)&0x08)
540  | ((scr[2] >> 5)&0x03);
541  p.scr[3] = 0x00 | ((scr[2] << 3)&0xF8) | ((scr[3] >> 5)&0x07);
542  p.scr[4] = 0x04 | ((scr[3] << 3)&0xF8) | ((scr_ext >> 7)&0x03);
543  p.scr[5] = 0x01 | ((scr_ext << 1)&0xFF);
544 
545 
546  muxr = muxr/50;
547  p.mux_rate[0] = (uint8_t)(muxr >> 14);
548  p.mux_rate[1] = (uint8_t)(0xff & (muxr >> 6));
549  p.mux_rate[2] = (uint8_t)(0x03 | ((muxr & 0x3f) << 2));
550 
551  p.stuff_length = 0xF8;
552 
553  if (navpack){
554  p.sheader_llength[0] = 0x00;
555  p.sheader_llength[1] = 0x12;
556 
557  setl_ps(&p);
558 
559  p.rate_bound[0] = (uint8_t)(0x80 | (muxr >>15));
560  p.rate_bound[1] = (uint8_t)(0xff & (muxr >> 7));
561  p.rate_bound[2] = (uint8_t)(0x01 | ((muxr & 0x7f)<<1));
562 
563 
564  p.audio_bound = (uint8_t)((audio_bound << 2)|(fixed << 1)|CSPS);
565  p.video_bound = (uint8_t)((audio_lock << 7)|
566  (video_lock << 6)|0x20|video_bound);
567  p.reserved = (uint8_t)(0xFF >> 1);
568 
569  p.data[0] = 0xB9;
570  p.data[1] = 0xE0;
571  p.data[2] = 0xE8;
572  p.data[3] = 0xB8;
573  p.data[4] = 0xC0;
574  p.data[5] = 0x20;
575  p.data[6] = 0xbd;
576  p.data[7] = 0xe0;
577  p.data[8] = 0x3a;
578  p.data[9] = 0xBF;
579  p.data[10] = 0xE0;
580  p.data[11] = 0x02;
581 
582  cwrite_ps(buf, &p, PS_HEADER_L2);
583  kill_ps(&p);
584  return PS_HEADER_L2;
585  }
586  cwrite_ps(buf, &p, PS_HEADER_L1);
587  kill_ps(&p);
588  return PS_HEADER_L1;
589 }
590 
591 using pts_arr = std::array<uint8_t,5>;
592 
593 static void get_pespts(const uint8_t *spts, pts_arr &pts)
594 {
595  //Make sure to set the 1st 4 bits properly
596  pts[0] = 0x01 |
597  ((spts[0] & 0xC0) >>5);
598  pts[1] = ((spts[0] & 0x3F) << 2) |
599  ((spts[1] & 0xC0) >> 6);
600  pts[2] = 0x01 | ((spts[1] & 0x3F) << 2) |
601  ((spts[2] & 0x80) >> 6);
602  pts[3] = ((spts[2] & 0x7F) << 1) |
603  ((spts[3] & 0x80) >> 7);
604  pts[4] = 0x01 | ((spts[3] & 0x7F) << 1);
605 }
606 
607 int write_pes_header(uint8_t id, int length , uint64_t PTS, uint64_t DTS,
608  uint8_t *obuf, int stuffing, uint8_t ptsdts)
609 {
610  std::array<uint8_t,2> le {};
611  std::array<uint8_t,3> dummy {};
612  pts_arr ppts {};
613  pts_arr pdts {};
614  std::array<uint8_t,3> headr {0x00, 0x00, 0x01};
615 
616  uint32_t lpts = htonl((PTS/300ULL) & 0x00000000FFFFFFFFULL);
617  auto *pts = (uint8_t *) &lpts;
618  get_pespts(pts,ppts);
619  if ((PTS/300ULL) & 0x0000000100000000ULL) ppts[0] |= 0x80;
620 
621  uint32_t ldts = htonl((DTS/300ULL) & 0x00000000FFFFFFFFULL);
622  auto *dts = (uint8_t *) &ldts;
623  get_pespts(dts,pdts);
624  if ((DTS/300ULL) & 0x0000000100000000ULL) pdts[0] |= 0x80;
625 
626  int c = 0;
627  memcpy(obuf+c,headr.data(),3);
628  c += 3;
629  memcpy(obuf+c,&id,1);
630  c++;
631 
632  le[0] = 0;
633  le[1] = 0;
634  length -= 6;
635 
636  le[0] |= ((uint8_t)(length >> 8) & 0xFF);
637  le[1] |= ((uint8_t)(length) & 0xFF);
638  memcpy(obuf+c,le.data(),2);
639  c += 2;
640 
641  if (id == PADDING_STREAM){
642  memset(obuf+c,0xff,length);
643  c+= length;
644  return c;
645  }
646 
647  dummy[0] = 0x80;
648  dummy[1] = 0;
649  dummy[2] = stuffing;
650 
651  if (ptsdts == PTS_ONLY){
652  dummy[2] += 5;
653  dummy[1] |= PTS_ONLY;
654  ppts[0] |= 0x20;
655  } else if (ptsdts == PTS_DTS){
656  dummy[2] += 10;
657  dummy[1] |= PTS_DTS;
658  ppts[0] |= 0x30;
659  pdts[0] |= 0x10;
660  }
661 
662 
663  memcpy(obuf+c,dummy.data(),3);
664  c += 3;
665 
666  if (ptsdts == PTS_ONLY){
667  memcpy(obuf+c,ppts.data(),5);
668  c += 5;
669  } else if ( ptsdts == PTS_DTS ){
670  memcpy(obuf+c,ppts.data(),5);
671  c += 5;
672  memcpy(obuf+c,pdts.data(),5);
673  c += 5;
674  }
675 
676  memset(obuf+c,0xFF,stuffing);
677  c += stuffing;
678 
679  return c;
680 }
681 
682 void write_padding_pes( int pack_size, int extcnt,
683  uint64_t SCR, uint64_t muxr, uint8_t *buf)
684 {
685  int pos = 0;
686 
687  pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1, 1,
688  0);
689 
690  write_pes_header( PADDING_STREAM, pack_size-pos, 0, 0, buf+pos, 0, 0);
691 
692 }
693 
694 int write_video_pes( int pack_size, int extcnt, uint64_t vpts,
695  uint64_t vdts, uint64_t SCR, uint64_t muxr,
696  uint8_t *buf, int *vlength,
697  uint8_t ptsdts, ringbuffer *vrbuffer)
698 {
699  int stuff = 0;
700  int length = *vlength;
701 
702  if (! length) return 0;
703  int p = PS_HEADER_L1+PES_H_MIN;
704 
705  if ( ptsdts == PTS_ONLY){
706  p += 5;
707  } else if (ptsdts == PTS_DTS){
708  p += 10;
709  }
710 
711  if ( length+p >= pack_size){
712  length = pack_size;
713  } else {
714  if (pack_size - length - p <= PES_MIN){
715  stuff = pack_size - length-p;
716  length = pack_size;
717  } else {
718  length = length+p;
719  }
720  }
721 
722  int pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1,
723  1, 0);
724 
725  pos += write_pes_header( 0xE0, length-pos, vpts, vdts, buf+pos,
726  stuff, ptsdts);
727  if (length-pos > *vlength){
728  LOG(VB_GENERAL, LOG_ERR,
729  QString("WHAT THE HELL %1 > %2").arg(length-pos).arg(*vlength));
730  }
731 
732  int add = ring_read( vrbuffer, buf+pos, length-pos);
733  *vlength = add;
734  if (add < 0) return -1;
735  pos += add;
736 
737  if (pos+PES_MIN < pack_size){
738  write_pes_header( PADDING_STREAM, pack_size-pos, 0, 0,
739  buf+pos, 0, 0);
740  pos = pack_size;
741  }
742  return pos;
743 }
744 
745 int write_audio_pes( int pack_size, int extcnt, int n, uint64_t pts,
746  uint64_t SCR, uint32_t muxr, uint8_t *buf, int *alength,
747  uint8_t ptsdts, ringbuffer *arbuffer)
748 {
749  int stuff = 0;
750  int length = *alength;
751 
752  if (!length) return 0;
753  int p = PS_HEADER_L1+PES_H_MIN;
754 
755  if (ptsdts == PTS_ONLY){
756  p += 5;
757  }
758 
759  if ( length+p >= pack_size){
760  length = pack_size;
761  } else {
762  if (pack_size-length-p <= PES_MIN){
763  stuff = pack_size - length-p;
764  length = pack_size;
765  } else {
766  length = length+p;
767  }
768  }
769  int pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1,
770  1, 0);
771  pos += write_pes_header( 0xC0+n, length-pos, pts, 0, buf+pos, stuff,
772  ptsdts);
773  int add = ring_read( arbuffer, buf+pos, length-pos);
774  *alength = add;
775  if (add < 0) return -1;
776  pos += add;
777 
778  if (pos+PES_MIN < pack_size){
779  write_pes_header( PADDING_STREAM, pack_size-pos, 0,0,
780  buf+pos, 0, 0);
781  pos = pack_size;
782  }
783  if (pos != pack_size) {
784  LOG(VB_GENERAL, LOG_ERR, QString("apos: %1").arg(pos));
785  exit(1);
786  }
787 
788  return pos;
789 }
790 
791 int write_ac3_pes( int pack_size, int extcnt, int n,
792  uint64_t pts, uint64_t SCR,
793  uint32_t muxr, uint8_t *buf, int *alength, uint8_t ptsdts,
794  int nframes,int ac3_off, ringbuffer *ac3rbuffer)
795 {
796  int stuff = 0;
797  int length = *alength;
798 
799  if (!length) return 0;
800  int p = PS_HEADER_L1+PES_H_MIN+4;
801 
802  if (ptsdts == PTS_ONLY){
803  p += 5;
804  }
805 
806  if ( length+p >= pack_size){
807  length = pack_size;
808  } else {
809  if (pack_size-length-p <= PES_MIN){
810  stuff = pack_size - length-p;
811  length = pack_size;
812  } else {
813  length = length+p;
814  }
815  }
816  int pos = write_ps_header(buf,SCR,muxr, extcnt, 0, 0, 1, 1,
817  1, 0);
818 
819  pos += write_pes_header( PRIVATE_STREAM1, length-pos, pts, 0,
820  buf+pos, stuff, ptsdts);
821  buf[pos] = 0x80 + n;
822  buf[pos+1] = nframes;
823  buf[pos+2] = (ac3_off >> 8)& 0xFF;
824  buf[pos+3] = (ac3_off)& 0xFF;
825  pos += 4;
826 
827  int add = ring_read( ac3rbuffer, buf+pos, length-pos);
828  *alength = add;
829  if (add < 0) return -1;
830  pos += add;
831 
832  if (pos+PES_MIN < pack_size){
833  write_pes_header( PADDING_STREAM, pack_size-pos, 0,0,
834  buf+pos, 0, 0);
835  pos = pack_size;
836  }
837  if (pos != pack_size) {
838  LOG(VB_GENERAL, LOG_ERR, QString("apos: %1").arg(pos));
839  exit(1);
840  }
841 
842  return pos;
843 }
844 
845 int write_nav_pack(int pack_size, int extcnt, uint64_t SCR, uint32_t muxr,
846  uint8_t *buf)
847 {
848  int pos = 0;
849  std::array<uint8_t,5> headr {0x00, 0x00, 0x01, PRIVATE_STREAM2, 0x03 };
850  (void)pack_size;
851 
852  pos = write_ps_header( buf, SCR, muxr, extcnt, 0, 0, 1, 1, 1, 1);
853  memcpy(buf+pos, headr.data(), 5);
854  buf[pos+5] = 0xD4;
855  pos += 6;
856  memset(buf+pos, 0, 0x03d4);
857  pos += 0x03d4;
858 
859  memcpy(buf+pos, headr.data(), 5);
860  buf[pos+5] = 0xFA;
861  pos += 6;
862  memset(buf+pos, 0, 0x03fA);
863  pos += 0x03fA;
864 
865  return pos;
866 }
PROG_STREAM_DIR
#define PROG_STREAM_DIR
Definition: pes.h:34
PRIVATE_STREAM1
#define PRIVATE_STREAM1
Definition: pes.h:23
SYS_START
#define SYS_START
Definition: pes.h:21
pes.h
MAX_PLENGTH
#define MAX_PLENGTH
Definition: pes.h:49
write_ps_header
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:510
PS_HEADER_L2
#define PS_HEADER_L2
Definition: pes.h:14
ringbuffer
Definition: ringbuffer.h:39
cwrite_ps
static int cwrite_ps(uint8_t *buf, ps_packet *p, uint32_t length)
Definition: pes.cpp:467
VIDEO_STREAM_S
#define VIDEO_STREAM_S
Definition: pes.h:28
ps_packet
Definition: pes.h:55
PES_MIN
#define PES_MIN
Definition: pes.h:15
init_ps
static void init_ps(ps_packet *p)
Definition: pes.cpp:437
write_video_pes
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:694
ptsinc
static void ptsinc(uint64_t *pts1, uint64_t pts2)
Definition: pes.h:127
MMAX_PLENGTH
#define MMAX_PLENGTH
Definition: pes.h:50
printpts
void printpts(int64_t pts)
Definition: pes.cpp:43
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
kill_ps
static void kill_ps(ps_packet *p)
Definition: pes.cpp:447
get_pespts
static void get_pespts(const uint8_t *spts, pts_arr &pts)
Definition: pes.cpp:593
PROG_STREAM_MAP
#define PROG_STREAM_MAP
Definition: pes.h:22
ptsdiff
int64_t ptsdiff(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:78
ECM_STREAM
#define ECM_STREAM
Definition: pes.h:30
PES_H_MIN
#define PES_H_MIN
Definition: pes.h:16
PRIVATE_STREAM2
#define PRIVATE_STREAM2
Definition: pes.h:25
write_ac3_pes
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:791
mythlogging.h
MAX_PTS2
#define MAX_PTS2
Definition: pes.h:53
PS_HEADER_L1
#define PS_HEADER_L1
Definition: pes.h:13
hardwareprofile.config.p
p
Definition: config.py:33
hardwareprofile.i18n.t
t
Definition: i18n.py:36
PTS_ONLY
#define PTS_ONLY
Definition: pes.h:46
PACK_START
#define PACK_START
Definition: pes.h:20
ring_write
int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:92
AUDIO_STREAM_E
#define AUDIO_STREAM_E
Definition: pes.h:27
ISO13522_STREAM
#define ISO13522_STREAM
Definition: pes.h:33
MAX_PTS
#define MAX_PTS
Definition: pes.h:52
setl_ps
static void setl_ps(ps_packet *p)
Definition: pes.cpp:460
ring_wpos
static int ring_wpos(ringbuffer *rbuf)
Definition: ringbuffer.h:77
get_pes
void get_pes(pes_in_t *p, uint8_t *buf, int count, void(*func)(pes_in_t *p))
Definition: pes.cpp:167
uptsdiff
uint64_t uptsdiff(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:104
ring_read
int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:202
write_padding_pes
void write_padding_pes(int pack_size, int extcnt, uint64_t SCR, uint64_t muxr, uint8_t *buf)
Definition: pes.cpp:682
DSM_CC_STREAM
#define DSM_CC_STREAM
Definition: pes.h:32
init_pes_in
void init_pes_in(pes_in_t *p, int t, ringbuffer *rb, int wi)
Definition: pes.cpp:147
write_nav_pack
int write_nav_pack(int pack_size, int extcnt, uint64_t SCR, uint32_t muxr, uint8_t *buf)
Definition: pes.cpp:845
VIDEO_STREAM_E
#define VIDEO_STREAM_E
Definition: pes.h:29
setlength_ps
static void setlength_ps(ps_packet *p)
Definition: pes.cpp:454
AUDIO_STREAM_S
#define AUDIO_STREAM_S
Definition: pes.h:26
write_pes_header
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:607
mpeg::chrono::pts
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
Definition: mythchrono.h:55
PADDING_STREAM
#define PADDING_STREAM
Definition: pes.h:24
write_audio_pes
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:745
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
ptscmp
int ptscmp(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:114
printptss
void printptss(int64_t pts)
Definition: pes.cpp:60
pes_in_t
Definition: pes.h:70
PTS_DTS
#define PTS_DTS
Definition: pes.h:47
EMM_STREAM
#define EMM_STREAM
Definition: pes.h:31
pts_arr
std::array< uint8_t, 5 > pts_arr
Definition: pes.cpp:591
ptsadd
uint64_t ptsadd(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:140