MythTV  0.26-pre
ts.c
Go to the documentation of this file.
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 *) &lscr;
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends