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  register int i;
181  const unsigned char *u = d; // Saves '& 0xff'
182 
183  for (i=0; i<len; i++)
184  crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *u++)];
185 
186  return crc;
187 }
188 
189 static int write_ts_header(int pid, int payload_start, int count,
190  int64_t SCR, uint8_t *obuf, int stuff)
191 {
192  int c = 0;
193  uint8_t *scr;
194  uint32_t lscr;
195  uint16_t scr_ext = 0;
196 
197  obuf[c++] = 0x47;
198  obuf[c++] = (payload_start ? 0x40 : 0x00) | ((pid >> 8) & 0x1f);
199  obuf[c++] = pid & 0xff;
200  obuf[c++] = ((SCR >= 0 || stuff) ? 0x30 : 0x10) | count;
201  if (SCR >= 0|| stuff) {
202  if (stuff)
203  stuff--;
204  int size = stuff;
205  unsigned char flags = 0;
206  if(SCR >= 0) {
207  if(size < 7)
208  size = 7;
209  flags |= 0x10;
210  }
211  obuf[c++] = size;
212  if(size) {
213  obuf[c++] = flags;
214  size--;
215  }
216  if(SCR >= 0) {
217  uint8_t bit;
218  lscr = (uint32_t) ((SCR/300ULL) & 0xFFFFFFFFULL);
219  bit = (lscr & 0x01) << 7;
220  lscr = htonl(lscr >> 1);
221  scr = (uint8_t *) &lscr;
222  scr_ext = (uint16_t) ((SCR%300ULL) & 0x1FFULL);
223  obuf[c++] = scr[0];
224  obuf[c++] = scr[1];
225  obuf[c++] = scr[2];
226  obuf[c++] = scr[3];
227  obuf[c++] = bit | 0x7e | (scr_ext >> 8);
228  obuf[c++] = scr_ext & 0xff;
229  size -= 6;
230  }
231  while(size-- > 0)
232  obuf[c++] = 0xff;
233  }
234  return c;
235 }
236 
237 int write_video_ts(uint64_t vpts, uint64_t vdts, uint64_t SCR, uint8_t *buf,
238  int *vlength, uint8_t ptsdts, ringbuffer *vrbuffer)
239 {
240 //Unlike program streams, we only do one PES per frame
241  static int count = 0;
242  int add;
243  int pos = 0;
244  int p = 0;
245  int stuff = 0;
246  int length = *vlength;
247 
248  if (! length) return 0;
249  p = 4;
250  if ( ptsdts ) {
251  p += PES_H_MIN + 8;
252 
253  if ( ptsdts == PTS_ONLY) {
254  p += 5;
255  } else if (ptsdts == PTS_DTS){
256  p += 10;
257  }
258  }
259  if ( length+p >= TS_SIZE){
260  length = TS_SIZE;
261  } else {
262  stuff = TS_SIZE - length - p;
263  length = TS_SIZE;
264  }
265  if(ptsdts) {
266 #if 0
267  LOG(VB_GENERAL, LOG_INFO, "SCR: %f PTS: %f DTS: %f",
268  SCR/27000000.0, vpts / 27000000.0, vdts / 27000000.0);
269 #endif
270  pos = write_ts_header(TS_VIDPID, 1, count, SCR, buf, stuff);
271  // always use length == 0 for video streams
272  pos += write_pes_header( 0xE0, 6, vpts, vdts, buf+pos,
273  0, ptsdts);
274  } else {
275  pos = write_ts_header(TS_VIDPID, 0, count, -1, buf, stuff);
276  }
277  count = (count+1) & 0x0f;
278 
279  if (length-pos > *vlength){
280  LOG(VB_GENERAL, LOG_ERR, "WHAT THE HELL %d > %d\n", length-pos,
281  *vlength);
282  }
283 
284  add = ring_read( vrbuffer, buf+pos, length-pos);
285  *vlength = add;
286  if (add < 0) return -1;
287  pos += add;
288 
289  return pos;
290 }
291 
292 int write_audio_ts(int n, uint64_t pts, uint8_t *buf, int *alength,
293  uint8_t ptsdts, ringbuffer *arbuffer)
294 {
295  static int count[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
296  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
297  int add;
298  int pos = 0;
299  int p = 0;
300  int stuff = 0;
301  int length = *alength;
302 
303  if (!length) return 0;
304  p = 4;
305 
306  if (ptsdts == PTS_ONLY){
307  p += PES_H_MIN + 5;
308  }
309 
310  if ( length+p >= TS_SIZE){
311  length = TS_SIZE;
312  } else {
313  stuff = TS_SIZE - length - p;
314  length = TS_SIZE;
315  }
316  if(ptsdts) {
317  pos = write_ts_header(TS_MP2PID+n, 1, count[n], -1, buf, stuff);
318  pos += write_pes_header( 0xC0+n, *alength + PES_H_MIN + 5, pts,
319  0, buf+pos, 0, ptsdts);
320  } else {
321  pos = write_ts_header(TS_MP2PID+n, 0, count[n], -1, buf, stuff);
322  }
323  count[n] = (count[n]+1) & 0x0f;
324  add = ring_read( arbuffer, buf+pos, length-pos);
325  *alength = add;
326  if (add < 0) return -1;
327  pos += add;
328 
329  if (pos != TS_SIZE) {
330  LOG(VB_GENERAL, LOG_ERR, "apos: %d", pos);
331  exit(1);
332  }
333 
334  return pos;
335 }
336 
337 int write_ac3_ts(int n, uint64_t pts, uint8_t *buf, int *alength,
338  uint8_t ptsdts, int nframes, ringbuffer *ac3rbuffer)
339 {
340  static int count[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
341  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
342  int add;
343  int pos = 0;
344  int p = 0;
345  int stuff = 0;
346  int length = *alength;
347 
348  if (!length) return 0;
349  p = 4;
350 
351  if (ptsdts == PTS_ONLY){
352  p += PES_H_MIN + 5 + 4; //PES header + PTS + PS1
353  }
354 
355  if ( length+p >= TS_SIZE){
356  length = TS_SIZE;
357  } else {
358  stuff = TS_SIZE - length - p;
359  length = TS_SIZE;
360  }
361  if(ptsdts) {
362  pos = write_ts_header(TS_AC3PID+n, 1, count[n], -1, buf, stuff);
364  *alength + 4 + PES_H_MIN + 5,
365  pts, 0, buf+pos, 0, ptsdts);
366  buf[pos] = 0x80 + n;
367  buf[pos+1] = nframes;
368  buf[pos+2] = 0x00;
369  buf[pos+3] = 0x00;
370  pos += 4;
371  } else {
372  pos = write_ts_header(TS_AC3PID+n, 0, count[n], -1, buf, stuff);
373  }
374  count[n] = (count[n]+1) & 0x0f;
375 
376  add = ring_read( ac3rbuffer, buf+pos, length-pos);
377  *alength = add;
378  if (add < 0) return -1;
379  pos += add;
380 
381  if (pos != TS_SIZE) {
382  LOG(VB_GENERAL, LOG_ERR, "apos: %d", pos);
383  exit(1);
384  }
385 
386  return pos;
387 }
388 
389 void write_ts_patpmt(extdata_t *ext, int extcnt, uint8_t prog_num, uint8_t *buf)
390 {
391 #define PMTPID 0x20
392  static int count = 0;
393  int pos, i, pmtpos = 13;
394  //PMT Program number = 1
395  //PMT PID = 0x20
396  uint8_t pat[17] = {0x00, 0x00, 0xb0, 0x0d, 0xfe, 0xef, 0xc1, 0x00, 0x00,
397  0x00, 0x00, 0xe0, PMTPID, 0x00, 0x00, 0x00, 0x00};
398  uint8_t pmt[184] ={0x00, 0x02, 0xb0, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00,
399  0x00, 0x00, 0xf0, 0x00};
400 
401  //PAT
402  pat[10] = prog_num;
403  pos = write_ts_header(0x00, 1, count, -1, buf, 0);
404  *(uint32_t *)(pat+13)= htonl(crc32_04c11db7(pat+1, 12, 0xffffffff));
405  memcpy(buf+pos, pat, 17);
406  pos += 17;
407  memset(buf+pos, 0xff, TS_SIZE - pos);
408  pos = TS_SIZE;
409  //PMT
410  pos += write_ts_header(PMTPID, 1, count, -1, buf+pos, 0);
411  for(i = 0; i <= extcnt; i++) {
412  uint8_t type;
413  uint32_t pid;
414  int n = ext[i-1].strmnum;
415  if(i == 0) {
416  type = 0x02;
417  pid = TS_VIDPID;
418  } else if(ext[i-1].type == MPEG_AUDIO) {
419  type = 0x04;
420  pid = TS_MP2PID + n;
421  } else if(ext[i-1].type == AC3) {
422  type = 0x81;
423  pid = TS_AC3PID + n;
424  } else {
425  type = 0xff;
426  pid = 0x1fff;
427  }
428  pmt[pmtpos++] = type;
429  pmt[pmtpos++] = 0xe0 | (0xff & (pid >> 8));
430  pmt[pmtpos++] = 0xff & pid;
431  pmt[pmtpos++] = 0xf0;
432  if(strlen(ext[i-1].language) == 3) {
433  pmt[pmtpos++] = 0x06;
434  pmt[pmtpos++] = 0x0a;
435  pmt[pmtpos++] = 0x04;
436  pmt[pmtpos++] = ext[i-1].language[0];
437  pmt[pmtpos++] = ext[i-1].language[1];
438  pmt[pmtpos++] = ext[i-1].language[2];
439  pmt[pmtpos++] = 0x00;
440  } else {
441  pmt[pmtpos++] = 0x00;
442  }
443  }
444  pmt[3] = pmtpos + 4/*crc*/ - 3 - 1/*pointer_field*/;
445  pmt[5] = prog_num;
446  pmt[9] = 0xf0 | (0xff & (TS_VIDPID >> 8));
447  pmt[10] = 0xff & TS_VIDPID;
448  *(uint32_t *)&pmt[pmtpos] = htonl(crc32_04c11db7(&pmt[1], pmtpos -1,
449  0xffffffff));
450  pmtpos+=4;
451  memcpy(buf+pos, pmt, pmtpos);
452  pos += pmtpos;
453  memset(buf+pos, 0xff, 2*TS_SIZE - pos);
454  pos = 2*TS_SIZE;
455  count = (count+1) & 0x0f;
456 }
int write_audio_ts(int n, uint64_t pts, uint8_t *buf, int *alength, uint8_t ptsdts, ringbuffer *arbuffer)
Definition: ts.c:292
#define NULL
Definition: H264Parser.h:62
static unsigned int crc_table[256]
Definition: ts.c:133
Definition: element.h:83
int write_ac3_ts(int n, uint64_t pts, uint8_t *buf, int *alength, uint8_t ptsdts, int nframes, ringbuffer *ac3rbuffer)
Definition: ts.c:337
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:237
uint16_t get_pid(const uint8_t *pid)
Definition: ts.c:46
unsigned char b
Definition: ParseText.cpp:329
int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.c:189
#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:389
#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 pp(VideoFilter *vf, VideoFrame *frame, int field)
static int write_ts_header(int pid, int payload_start, int count, int64_t SCR, uint8_t *obuf, int stuff)
Definition: ts.c:189
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:607
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