00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <stdlib.h>
00030 #include <stdint.h>
00031 #include <string.h>
00032 #include <stdio.h>
00033
00034 #ifdef USING_MINGW
00035 #include <winsock2.h>
00036 #else
00037 #include <netinet/in.h>
00038 #endif
00039
00040 #include "ts.h"
00041 #include "element.h"
00042 #include "pes.h"
00043
00044 #include "mythlogging.h"
00045
00046 uint16_t get_pid(uint8_t *pid)
00047 {
00048 uint16_t pp = 0;
00049
00050 pp = (pid[0] & PID_MASK_HI)<<8;
00051 pp |= pid[1];
00052
00053 return pp;
00054 }
00055
00056 int find_pids_pos(uint16_t *vpid, uint16_t *apid, uint16_t *ac3pid,uint8_t *buf, int len, int *vpos, int *apos, int *ac3pos)
00057 {
00058 int c=0;
00059 int found=0;
00060
00061 if (!vpid || !apid || !ac3pid || !buf || !len) return 0;
00062
00063 *vpid = 0;
00064 *apid = 0;
00065 *ac3pid = 0;
00066
00067 while ( c+TS_SIZE < len){
00068 if (buf[c] == buf[c+TS_SIZE]) break;
00069 c++;
00070 }
00071
00072 while(found<2 && c < len){
00073 if (buf[c+1] & PAY_START) {
00074 int off = 4;
00075
00076 if ( buf[c+3] & ADAPT_FIELD) {
00077 off += buf[c+4] + 1;
00078 }
00079
00080 if (off < TS_SIZE-4){
00081 if (!*vpid && (buf[c+off+3] & 0xF0) == 0xE0){
00082 *vpid = get_pid(buf+c+1);
00083 if (vpos) *vpos = c+off+3;
00084 found++;
00085 }
00086 if (!*ac3pid && buf[c+off+3] == 0xBD){
00087 int l=off+4;
00088 int f=0;
00089
00090 while ( l < TS_SIZE && f<2){
00091 uint8_t b=buf[c+l];
00092 switch(f){
00093 case 0:
00094 if ( b == 0x0b)
00095 f = 1;
00096 break;
00097
00098 case 1:
00099 if ( b == 0x77)
00100 f = 2;
00101 else if ( b != 0x0b)
00102 f = 0;
00103 }
00104 l++;
00105 }
00106 if (f==2){
00107 *ac3pid = get_pid(buf+c+1);
00108 if (ac3pos) *ac3pos = c+off+3;
00109 found++;
00110 }
00111 }
00112 if (!*apid && ((buf[c+off+3] & 0xF0) == 0xC0 ||
00113 (buf[c+off+3] & 0xF0) == 0xD0)){
00114 *apid = get_pid(buf+c+1);
00115 if (apos) *apos = c+off+3;
00116 found++;
00117 }
00118 }
00119 }
00120 c+= TS_SIZE;
00121 }
00122 return found;
00123 }
00124
00125
00126 int find_pids(uint16_t *vpid, uint16_t *apid, uint16_t *ac3pid,uint8_t *buf, int len)
00127 {
00128 return find_pids_pos(vpid, apid, ac3pid, buf, len, NULL, NULL, NULL);
00129 }
00130
00131
00132
00133 static unsigned int crc_table[256] = {
00134 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
00135 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
00136 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
00137 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
00138 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
00139 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
00140 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
00141 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
00142 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
00143 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
00144 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
00145 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
00146 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
00147 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
00148 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
00149 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
00150 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
00151 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
00152 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
00153 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
00154 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
00155 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
00156 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
00157 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
00158 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
00159 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
00160 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
00161 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
00162 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
00163 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
00164 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
00165 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
00166 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
00167 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
00168 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
00169 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
00170 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
00171 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
00172 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
00173 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
00174 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
00175 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
00176 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
00177
00178 static unsigned int crc32_04c11db7 (const unsigned char *d, int len, unsigned int crc)
00179 {
00180 register int i;
00181 const unsigned char *u = d;
00182
00183 for (i=0; i<len; i++)
00184 crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *u++)];
00185
00186 return crc;
00187 }
00188
00189 static int write_ts_header(int pid, int payload_start, int count,
00190 int64_t SCR, uint8_t *obuf, int stuff)
00191 {
00192 int c = 0;
00193 uint8_t *scr;
00194 uint32_t lscr;
00195 uint16_t scr_ext = 0;
00196
00197 obuf[c++] = 0x47;
00198 obuf[c++] = (payload_start ? 0x40 : 0x00) | ((pid >> 8) & 0x1f);
00199 obuf[c++] = pid & 0xff;
00200 obuf[c++] = ((SCR >= 0 || stuff) ? 0x30 : 0x10) | count;
00201 if (SCR >= 0|| stuff) {
00202 if (stuff)
00203 stuff--;
00204 int size = stuff;
00205 unsigned char flags = 0;
00206 if(SCR >= 0) {
00207 if(size < 7)
00208 size = 7;
00209 flags |= 0x10;
00210 }
00211 obuf[c++] = size;
00212 if(size) {
00213 obuf[c++] = flags;
00214 size--;
00215 }
00216 if(SCR >= 0) {
00217 uint8_t bit;
00218 lscr = (uint32_t) ((SCR/300ULL) & 0xFFFFFFFFULL);
00219 bit = (lscr & 0x01) << 7;
00220 lscr = htonl(lscr >> 1);
00221 scr = (uint8_t *) 𝓁
00222 scr_ext = (uint16_t) ((SCR%300ULL) & 0x1FFULL);
00223 obuf[c++] = scr[0];
00224 obuf[c++] = scr[1];
00225 obuf[c++] = scr[2];
00226 obuf[c++] = scr[3];
00227 obuf[c++] = bit | 0x7e | (scr_ext >> 8);
00228 obuf[c++] = scr_ext & 0xff;
00229 size -= 6;
00230 }
00231 while(size-- > 0)
00232 obuf[c++] = 0xff;
00233 }
00234 return c;
00235 }
00236
00237 int write_video_ts(uint64_t vpts, uint64_t vdts, uint64_t SCR, uint8_t *buf,
00238 int *vlength, uint8_t ptsdts, ringbuffer *vrbuffer)
00239 {
00240
00241 static int count = 0;
00242 int add;
00243 int pos = 0;
00244 int p = 0;
00245 int stuff = 0;
00246 int length = *vlength;
00247
00248 if (! length) return 0;
00249 p = 4;
00250 if ( ptsdts ) {
00251 p += PES_H_MIN + 8;
00252
00253 if ( ptsdts == PTS_ONLY) {
00254 p += 5;
00255 } else if (ptsdts == PTS_DTS){
00256 p += 10;
00257 }
00258 }
00259 if ( length+p >= TS_SIZE){
00260 length = TS_SIZE;
00261 } else {
00262 stuff = TS_SIZE - length - p;
00263 length = TS_SIZE;
00264 }
00265 if(ptsdts) {
00266 #if 0
00267 LOG(VB_GENERAL, LOG_INFO, "SCR: %f PTS: %f DTS: %f",
00268 SCR/27000000.0, vpts / 27000000.0, vdts / 27000000.0);
00269 #endif
00270 pos = write_ts_header(TS_VIDPID, 1, count, SCR, buf, stuff);
00271
00272 pos += write_pes_header( 0xE0, 6, vpts, vdts, buf+pos,
00273 0, ptsdts);
00274 } else {
00275 pos = write_ts_header(TS_VIDPID, 0, count, -1, buf, stuff);
00276 }
00277 count = (count+1) & 0x0f;
00278
00279 if (length-pos > *vlength){
00280 LOG(VB_GENERAL, LOG_ERR, "WHAT THE HELL %d > %d\n", length-pos,
00281 *vlength);
00282 }
00283
00284 add = ring_read( vrbuffer, buf+pos, length-pos);
00285 *vlength = add;
00286 if (add < 0) return -1;
00287 pos += add;
00288
00289 return pos;
00290 }
00291
00292 int write_audio_ts(int n, uint64_t pts, uint8_t *buf, int *alength,
00293 uint8_t ptsdts, ringbuffer *arbuffer)
00294 {
00295 static int count[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00296 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
00297 int add;
00298 int pos = 0;
00299 int p = 0;
00300 int stuff = 0;
00301 int length = *alength;
00302
00303 if (!length) return 0;
00304 p = 4;
00305
00306 if (ptsdts == PTS_ONLY){
00307 p += PES_H_MIN + 5;
00308 }
00309
00310 if ( length+p >= TS_SIZE){
00311 length = TS_SIZE;
00312 } else {
00313 stuff = TS_SIZE - length - p;
00314 length = TS_SIZE;
00315 }
00316 if(ptsdts) {
00317 pos = write_ts_header(TS_MP2PID+n, 1, count[n], -1, buf, stuff);
00318 pos += write_pes_header( 0xC0+n, *alength + PES_H_MIN + 5, pts,
00319 0, buf+pos, 0, ptsdts);
00320 } else {
00321 pos = write_ts_header(TS_MP2PID+n, 0, count[n], -1, buf, stuff);
00322 }
00323 count[n] = (count[n]+1) & 0x0f;
00324 add = ring_read( arbuffer, buf+pos, length-pos);
00325 *alength = add;
00326 if (add < 0) return -1;
00327 pos += add;
00328
00329 if (pos != TS_SIZE) {
00330 LOG(VB_GENERAL, LOG_ERR, "apos: %d", pos);
00331 exit(1);
00332 }
00333
00334 return pos;
00335 }
00336
00337 int write_ac3_ts(int n, uint64_t pts, uint8_t *buf, int *alength,
00338 uint8_t ptsdts, int nframes, ringbuffer *ac3rbuffer)
00339 {
00340 static int count[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00341 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
00342 int add;
00343 int pos = 0;
00344 int p = 0;
00345 int stuff = 0;
00346 int length = *alength;
00347
00348 if (!length) return 0;
00349 p = 4;
00350
00351 if (ptsdts == PTS_ONLY){
00352 p += PES_H_MIN + 5 + 4;
00353 }
00354
00355 if ( length+p >= TS_SIZE){
00356 length = TS_SIZE;
00357 } else {
00358 stuff = TS_SIZE - length - p;
00359 length = TS_SIZE;
00360 }
00361 if(ptsdts) {
00362 pos = write_ts_header(TS_AC3PID+n, 1, count[n], -1, buf, stuff);
00363 pos += write_pes_header( PRIVATE_STREAM1,
00364 *alength + 4 + PES_H_MIN + 5,
00365 pts, 0, buf+pos, 0, ptsdts);
00366 buf[pos] = 0x80 + n;
00367 buf[pos+1] = nframes;
00368 buf[pos+2] = 0x00;
00369 buf[pos+3] = 0x00;
00370 pos += 4;
00371 } else {
00372 pos = write_ts_header(TS_AC3PID+n, 0, count[n], -1, buf, stuff);
00373 }
00374 count[n] = (count[n]+1) & 0x0f;
00375
00376 add = ring_read( ac3rbuffer, buf+pos, length-pos);
00377 *alength = add;
00378 if (add < 0) return -1;
00379 pos += add;
00380
00381 if (pos != TS_SIZE) {
00382 LOG(VB_GENERAL, LOG_ERR, "apos: %d", pos);
00383 exit(1);
00384 }
00385
00386 return pos;
00387 }
00388
00389 void write_ts_patpmt(extdata_t *ext, int extcnt, uint8_t prog_num, uint8_t *buf)
00390 {
00391 #define PMTPID 0x20
00392 static int count = 0;
00393 int pos, i, pmtpos = 13;
00394
00395
00396 uint8_t pat[17] = {0x00, 0x00, 0xb0, 0x0d, 0xfe, 0xef, 0xc1, 0x00, 0x00,
00397 0x00, 0x00, 0xe0, PMTPID, 0x00, 0x00, 0x00, 0x00};
00398 uint8_t pmt[184] ={0x00, 0x02, 0xb0, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00,
00399 0x00, 0x00, 0xf0, 0x00};
00400
00401
00402 pat[10] = prog_num;
00403 pos = write_ts_header(0x00, 1, count, -1, buf, 0);
00404 *(uint32_t *)(pat+13)= htonl(crc32_04c11db7(pat+1, 12, 0xffffffff));
00405 memcpy(buf+pos, pat, 17);
00406 pos += 17;
00407 memset(buf+pos, 0xff, TS_SIZE - pos);
00408 pos = TS_SIZE;
00409
00410 pos += write_ts_header(PMTPID, 1, count, -1, buf+pos, 0);
00411 for(i = 0; i <= extcnt; i++) {
00412 uint8_t type;
00413 uint32_t pid;
00414 int n = ext[i-1].strmnum;
00415 if(i == 0) {
00416 type = 0x02;
00417 pid = TS_VIDPID;
00418 } else if(ext[i-1].type == MPEG_AUDIO) {
00419 type = 0x04;
00420 pid = TS_MP2PID + n;
00421 } else if(ext[i-1].type == AC3) {
00422 type = 0x81;
00423 pid = TS_AC3PID + n;
00424 } else {
00425 type = 0xff;
00426 pid = 0x1fff;
00427 }
00428 pmt[pmtpos++] = type;
00429 pmt[pmtpos++] = 0xe0 | (0xff & (pid >> 8));
00430 pmt[pmtpos++] = 0xff & pid;
00431 pmt[pmtpos++] = 0xf0;
00432 if(strlen(ext[i-1].language) == 3) {
00433 pmt[pmtpos++] = 0x06;
00434 pmt[pmtpos++] = 0x0a;
00435 pmt[pmtpos++] = 0x04;
00436 pmt[pmtpos++] = ext[i-1].language[0];
00437 pmt[pmtpos++] = ext[i-1].language[1];
00438 pmt[pmtpos++] = ext[i-1].language[2];
00439 pmt[pmtpos++] = 0x00;
00440 } else {
00441 pmt[pmtpos++] = 0x00;
00442 }
00443 }
00444 pmt[3] = pmtpos + 4 - 3 - 1;
00445 pmt[5] = prog_num;
00446 pmt[9] = 0xf0 | (0xff & (TS_VIDPID >> 8));
00447 pmt[10] = 0xff & TS_VIDPID;
00448 *(uint32_t *)&pmt[pmtpos] = htonl(crc32_04c11db7(&pmt[1], pmtpos -1,
00449 0xffffffff));
00450 pmtpos+=4;
00451 memcpy(buf+pos, pmt, pmtpos);
00452 pos += pmtpos;
00453 memset(buf+pos, 0xff, 2*TS_SIZE - pos);
00454 pos = 2*TS_SIZE;
00455 count = (count+1) & 0x0f;
00456 }