MythTV  master
ts.c
Go to the documentation of this file.
1 /*
2  * ts.c: MPEG TS 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 <stdlib.h>
30 #include <stdint.h>
31 #include <string.h>
32 #include <stdio.h>
33 
34 #ifdef _WIN32
35 #include <winsock2.h>
36 #else
37 #include <netinet/in.h>
38 #endif
39 
40 #include "ts.h"
41 #include "element.h"
42 #include "pes.h"
43 
44 #include "mythlogging.h"
45 
46 uint16_t get_pid(const uint8_t *pid)
47 {
48  uint16_t pp = 0;
49 
50  pp = (pid[0] & PID_MASK_HI)<<8;
51  pp |= pid[1];
52 
53  return pp;
54 }
55 
56 int find_pids_pos(uint16_t *vpid, uint16_t *apid, uint16_t *ac3pid,uint8_t *buf, int len, int *vpos, int *apos, int *ac3pos)
57 {
58  int c=0;
59  int found=0;
60 
61  if (!vpid || !apid || !ac3pid || !buf || !len) return 0;
62 
63  *vpid = 0;
64  *apid = 0;
65  *ac3pid = 0;
66 
67  while ( c+TS_SIZE < len){
68  if (buf[c] == buf[c+TS_SIZE]) break;
69  c++;
70  }
71 
72  while(found<2 && c < len){
73  if (buf[c+1] & PAY_START) {
74  int off = 4;
75 
76  if ( buf[c+3] & ADAPT_FIELD) { // adaptation field?
77  off += buf[c+4] + 1;
78  }
79 
80  if (off < TS_SIZE-4){
81  if (!*vpid && (buf[c+off+3] & 0xF0) == 0xE0){
82  *vpid = get_pid(buf+c+1);
83  if (vpos) *vpos = c+off+3;
84  found++;
85  }
86  if (!*ac3pid && buf[c+off+3] == 0xBD){
87  int l=off+4;
88  int f=0;
89 
90  while ( l < TS_SIZE && f<2){
91  uint8_t b=buf[c+l];
92  switch(f){
93  case 0:
94  if ( b == 0x0b)
95  f = 1;
96  break;
97 
98  case 1:
99  if ( b == 0x77)
100  f = 2;
101  else if ( b != 0x0b)
102  f = 0;
103  }
104  l++;
105  }
106  if (f==2){
107  *ac3pid = get_pid(buf+c+1);
108  if (ac3pos) *ac3pos = c+off+3;
109  found++;
110  }
111  }
112  if (!*apid && ((buf[c+off+3] & 0xF0) == 0xC0 ||
113  (buf[c+off+3] & 0xF0) == 0xD0)){
114  *apid = get_pid(buf+c+1);
115  if (apos) *apos = c+off+3;
116  found++;
117  }
118  }
119  }
120  c+= TS_SIZE;
121  }
122  return found;
123 }
124 
125 
126 int find_pids(uint16_t *vpid, uint16_t *apid, uint16_t *ac3pid,uint8_t *buf, int len)
127 {
128  return find_pids_pos(vpid, apid, ac3pid, buf, len, NULL, NULL, NULL);
129 }
130 
131 //taken and adapted from libdtv, (c) Rolf Hakenes
132 // CRC32 lookup table for polynomial 0x04c11db7
133 static unsigned int crc_table[256] = {
134  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
135  0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
136  0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
137  0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
138  0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
139  0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
140  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
141  0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
142  0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
143  0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
144  0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
145  0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
146  0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
147  0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
148  0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
149  0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
150  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
151  0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
152  0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
153  0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
154  0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
155  0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
156  0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
157  0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
158  0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
159  0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
160  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
161  0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
162  0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
163  0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
164  0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
165  0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
166  0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
167  0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
168  0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
169  0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
170  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
171  0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
172  0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
173  0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
174  0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
175  0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
176  0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
177 
178 static unsigned int crc32_04c11db7 (const unsigned char *d, int len, unsigned int crc)
179 {
180  const unsigned char *u = d; // Saves '& 0xff'
181 
182  for (int i=0; i<len; i++)
183  crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *u++)];
184 
185  return crc;
186 }
187 
188 static int write_ts_header(int pid, int payload_start, int count,
189  int64_t SCR, uint8_t *obuf, int stuff)
190 {
191  int c = 0;
192 
193  obuf[c++] = 0x47;
194  obuf[c++] = (payload_start ? 0x40 : 0x00) | ((pid >> 8) & 0x1f);
195  obuf[c++] = pid & 0xff;
196  obuf[c++] = ((SCR >= 0 || stuff) ? 0x30 : 0x10) | count;
197  if (SCR >= 0|| stuff) {
198  if (stuff)
199  stuff--;
200  int size = stuff;
201  unsigned char flags = 0;
202  if(SCR >= 0) {
203  if(size < 7)
204  size = 7;
205  flags |= 0x10;
206  }
207  obuf[c++] = size;
208  if(size) {
209  obuf[c++] = flags;
210  size--;
211  }
212  if(SCR >= 0) {
213  uint32_t lscr = (uint32_t) ((SCR/300ULL) & 0xFFFFFFFFULL);
214  uint8_t bit = (lscr & 0x01) << 7;
215  lscr = htonl(lscr >> 1);
216  uint8_t *scr = (uint8_t *) &lscr;
217  uint16_t scr_ext = (uint16_t) ((SCR%300ULL) & 0x1FFULL);
218  obuf[c++] = scr[0];
219  obuf[c++] = scr[1];
220  obuf[c++] = scr[2];
221  obuf[c++] = scr[3];
222  obuf[c++] = bit | 0x7e | (scr_ext >> 8);
223  obuf[c++] = scr_ext & 0xff;
224  size -= 6;
225  }
226  while(size-- > 0)
227  obuf[c++] = 0xff;
228  }
229  return c;
230 }
231 
232 int write_video_ts(uint64_t vpts, uint64_t vdts, uint64_t SCR, uint8_t *buf,
233  int *vlength, uint8_t ptsdts, ringbuffer *vrbuffer)
234 {
235 //Unlike program streams, we only do one PES per frame
236  static int s_count = 0;
237  int pos = 0;
238  int stuff = 0;
239  int length = *vlength;
240 
241  if (! length) return 0;
242  int p = 4;
243  if ( ptsdts ) {
244  p += PES_H_MIN + 8;
245 
246  if ( ptsdts == PTS_ONLY) {
247  p += 5;
248  } else if (ptsdts == PTS_DTS){
249  p += 10;
250  }
251  }
252  if ( length+p >= TS_SIZE){
253  length = TS_SIZE;
254  } else {
255  stuff = TS_SIZE - length - p;
256  length = TS_SIZE;
257  }
258  if(ptsdts) {
259 #if 0
260  LOG(VB_GENERAL, LOG_INFO, "SCR: %f PTS: %f DTS: %f",
261  SCR/27000000.0, vpts / 27000000.0, vdts / 27000000.0);
262 #endif
263  pos = write_ts_header(TS_VIDPID, 1, s_count, SCR, buf, stuff);
264  // always use length == 0 for video streams
265  pos += write_pes_header( 0xE0, 6, vpts, vdts, buf+pos,
266  0, ptsdts);
267  } else {
268  pos = write_ts_header(TS_VIDPID, 0, s_count, -1, buf, stuff);
269  }
270  s_count = (s_count+1) & 0x0f;
271 
272  if (length-pos > *vlength){
273  LOG(VB_GENERAL, LOG_ERR, "WHAT THE HELL %d > %d\n", length-pos,
274  *vlength);
275  }
276 
277  int add = ring_read( vrbuffer, buf+pos, length-pos);
278  *vlength = add;
279  if (add < 0) return -1;
280  pos += add;
281 
282  return pos;
283 }
284 
285 int write_audio_ts(int n, uint64_t pts, uint8_t *buf, int *alength,
286  uint8_t ptsdts, ringbuffer *arbuffer)
287 {
288  static int s_count[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
289  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
290  int pos = 0;
291  int stuff = 0;
292  int length = *alength;
293 
294  if (!length) return 0;
295  int p = 4;
296 
297  if (ptsdts == PTS_ONLY){
298  p += PES_H_MIN + 5;
299  }
300 
301  if ( length+p >= TS_SIZE){
302  length = TS_SIZE;
303  } else {
304  stuff = TS_SIZE - length - p;
305  length = TS_SIZE;
306  }
307  if(ptsdts) {
308  pos = write_ts_header(TS_MP2PID+n, 1, s_count[n], -1, buf, stuff);
309  pos += write_pes_header( 0xC0+n, *alength + PES_H_MIN + 5, pts,
310  0, buf+pos, 0, ptsdts);
311  } else {
312  pos = write_ts_header(TS_MP2PID+n, 0, s_count[n], -1, buf, stuff);
313  }
314  s_count[n] = (s_count[n]+1) & 0x0f;
315  int add = ring_read( arbuffer, buf+pos, length-pos);
316  *alength = add;
317  if (add < 0) return -1;
318  pos += add;
319 
320  if (pos != TS_SIZE) {
321  LOG(VB_GENERAL, LOG_ERR, "apos: %d", pos);
322  exit(1);
323  }
324 
325  return pos;
326 }
327 
328 int write_ac3_ts(int n, uint64_t pts, uint8_t *buf, int *alength,
329  uint8_t ptsdts, int nframes, ringbuffer *ac3rbuffer)
330 {
331  static int s_count[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
332  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
333  int pos = 0;
334  int stuff = 0;
335  int length = *alength;
336 
337  if (!length) return 0;
338  int p = 4;
339 
340  if (ptsdts == PTS_ONLY){
341  p += PES_H_MIN + 5 + 4; //PES header + PTS + PS1
342  }
343 
344  if ( length+p >= TS_SIZE){
345  length = TS_SIZE;
346  } else {
347  stuff = TS_SIZE - length - p;
348  length = TS_SIZE;
349  }
350  if(ptsdts) {
351  pos = write_ts_header(TS_AC3PID+n, 1, s_count[n], -1, buf, stuff);
353  *alength + 4 + PES_H_MIN + 5,
354  pts, 0, buf+pos, 0, ptsdts);
355  buf[pos] = 0x80 + n;
356  buf[pos+1] = nframes;
357  buf[pos+2] = 0x00;
358  buf[pos+3] = 0x00;
359  pos += 4;
360  } else {
361  pos = write_ts_header(TS_AC3PID+n, 0, s_count[n], -1, buf, stuff);
362  }
363  s_count[n] = (s_count[n]+1) & 0x0f;
364 
365  int add = ring_read( ac3rbuffer, buf+pos, length-pos);
366  *alength = add;
367  if (add < 0) return -1;
368  pos += add;
369 
370  if (pos != TS_SIZE) {
371  LOG(VB_GENERAL, LOG_ERR, "apos: %d", pos);
372  exit(1);
373  }
374 
375  return pos;
376 }
377 
378 void write_ts_patpmt(extdata_t *ext, int extcnt, uint8_t prog_num, uint8_t *buf)
379 {
380 #define PMTPID 0x20
381  static int s_count = 0;
382  int pmtpos = 13;
383  //PMT Program number = 1
384  //PMT PID = 0x20
385  uint8_t pat[17] = {0x00, 0x00, 0xb0, 0x0d, 0xfe, 0xef, 0xc1, 0x00, 0x00,
386  0x00, 0x00, 0xe0, PMTPID, 0x00, 0x00, 0x00, 0x00};
387  uint8_t pmt[184] ={0x00, 0x02, 0xb0, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00,
388  0x00, 0x00, 0xf0, 0x00};
389 
390  //PAT
391  pat[10] = prog_num;
392  int pos = write_ts_header(0x00, 1, s_count, -1, buf, 0);
393  *(uint32_t *)(pat+13)= htonl(crc32_04c11db7(pat+1, 12, 0xffffffff));
394  memcpy(buf+pos, pat, 17);
395  pos += 17;
396  memset(buf+pos, 0xff, TS_SIZE - pos);
397  pos = TS_SIZE;
398  //PMT
399  pos += write_ts_header(PMTPID, 1, s_count, -1, buf+pos, 0);
400  for(int i = 0; i <= extcnt; i++) {
401  uint8_t type = 0xFF;
402  uint32_t pid = 0x1FFF;
403  int n = ext[i-1].strmnum;
404  if(i == 0) {
405  type = 0x02;
406  pid = TS_VIDPID;
407  } else if(ext[i-1].type == MPEG_AUDIO) {
408  type = 0x04;
409  pid = TS_MP2PID + n;
410  } else if(ext[i-1].type == AC3) {
411  type = 0x81;
412  pid = TS_AC3PID + n;
413  } else {
414  type = 0xff;
415  pid = 0x1fff;
416  }
417  pmt[pmtpos++] = type;
418  pmt[pmtpos++] = 0xe0 | (0xff & (pid >> 8));
419  pmt[pmtpos++] = 0xff & pid;
420  pmt[pmtpos++] = 0xf0;
421  if(strlen(ext[i-1].language) == 3) {
422  pmt[pmtpos++] = 0x06;
423  pmt[pmtpos++] = 0x0a;
424  pmt[pmtpos++] = 0x04;
425  pmt[pmtpos++] = ext[i-1].language[0];
426  pmt[pmtpos++] = ext[i-1].language[1];
427  pmt[pmtpos++] = ext[i-1].language[2];
428  pmt[pmtpos++] = 0x00;
429  } else {
430  pmt[pmtpos++] = 0x00;
431  }
432  }
433  pmt[3] = pmtpos + 4/*crc*/ - 3 - 1/*pointer_field*/;
434  pmt[5] = prog_num;
435  pmt[9] = 0xf0 | (0xff & (TS_VIDPID >> 8));
436  pmt[10] = 0xff & TS_VIDPID;
437  *(uint32_t *)&pmt[pmtpos] = htonl(crc32_04c11db7(&pmt[1], pmtpos -1,
438  0xffffffff));
439  pmtpos+=4;
440  memcpy(buf+pos, pmt, pmtpos);
441  pos += pmtpos;
442  memset(buf+pos, 0xff, 2*TS_SIZE - pos);
443 // pos = 2*TS_SIZE;
444  s_count = (s_count+1) & 0x0f;
445 }
int write_audio_ts(int n, uint64_t pts, uint8_t *buf, int *alength, uint8_t ptsdts, ringbuffer *arbuffer)
Definition: ts.c:285
#define NULL
Definition: H264Parser.h:62
Definition: element.h:83
static unsigned int crc_table[256]
Definition: ts.c:133
int write_ac3_ts(int n, uint64_t pts, uint8_t *buf, int *alength, uint8_t ptsdts, int nframes, ringbuffer *ac3rbuffer)
Definition: ts.c:328
static unsigned int crc32_04c11db7(const unsigned char *d, int len, unsigned int crc)
Definition: ts.c:178
#define TS_AC3PID
Definition: ts.h:63
#define PRIVATE_STREAM1
Definition: pes.h:23
#define PTS_ONLY
Definition: pes.h:46
int write_video_ts(uint64_t vpts, uint64_t vdts, uint64_t SCR, uint8_t *buf, int *vlength, uint8_t ptsdts, ringbuffer *vrbuffer)
Definition: ts.c:232
uint16_t get_pid(const uint8_t *pid)
Definition: ts.c:46
int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.c:178
#define PAY_START
Definition: ts.h:35
void write_ts_patpmt(extdata_t *ext, int extcnt, uint8_t prog_num, uint8_t *buf)
Definition: ts.c:378
#define PID_MASK_HI
Definition: ts.h:37
int find_pids(uint16_t *vpid, uint16_t *apid, uint16_t *ac3pid, uint8_t *buf, int len)
Definition: ts.c:126
static int write_ts_header(int pid, int payload_start, int count, int64_t SCR, uint8_t *obuf, int stuff)
Definition: ts.c:188
static const uint16_t * d
unsigned short uint16_t
Definition: iso6937tables.h:1
int find_pids_pos(uint16_t *vpid, uint16_t *apid, uint16_t *ac3pid, uint8_t *buf, int len, int *vpos, int *apos, int *ac3pos)
Definition: ts.c:56
#define TS_SIZE
#define PES_H_MIN
Definition: pes.h:16
char language[4]
Definition: mpg_common.h:61
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.c:598
int strmnum
Definition: mpg_common.h:59
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
#define ADAPT_FIELD
Definition: ts.h:42
#define PMTPID
#define TS_MP2PID
Definition: ts.h:62
#define PTS_DTS
Definition: pes.h:47
#define TS_VIDPID
Definition: ts.h:61