|
MythTV
0.26-pre
|
00001 /* 00002 * ts.c: MPEG TS functions for replex 00003 * 00004 * 00005 * Copyright (C) 2003 Marcus Metzler <mocm@metzlerbros.de> 00006 * Metzler Brothers Systementwicklung GbR 00007 * Changes to use MythTV logging 00008 * Copyright (C) 2011 Gavin Hurlbut <ghurlbut@mythtv.org> 00009 * 00010 * This program is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU General Public License 00012 * as published by the Free Software Foundation; either version 2 00013 * of the License, or (at your option) any later version. 00014 * 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * General Public License for more details. 00020 * 00021 * 00022 * You should have received a copy of the GNU General Public License 00023 * along with this program; if not, write to the Free Software 00024 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00025 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 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) { // adaptation 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 //taken and adapted from libdtv, (c) Rolf Hakenes 00132 // CRC32 lookup table for polynomial 0x04c11db7 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; // Saves '& 0xff' 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 //Unlike program streams, we only do one PES per frame 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 // always use length == 0 for video streams 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; //PES header + PTS + PS1 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 //PMT Program number = 1 00395 //PMT PID = 0x20 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 //PAT 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 //PMT 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/*crc*/ - 3 - 1/*pointer_field*/; 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 }
1.7.6.1