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