From 9b144d30e0ea8ce900c37b96ba2cbdda14b0ae88 Mon Sep 17 00:00:00 2001 From: kwacker Date: Sun, 11 Apr 2010 13:46:11 +0200 Subject: Burn 0.2.0-beta3 und Streamdev mit Paches aktualisiert --- .../streamdev/streamdev-cvs/libdvbmpeg/.cvsignore | 1 + .../streamdev/streamdev-cvs/libdvbmpeg/CVS/Entries | 11 + .../streamdev-cvs/libdvbmpeg/CVS/Repository | 1 + .../streamdev/streamdev-cvs/libdvbmpeg/CVS/Root | 1 + .../streamdev/streamdev-cvs/libdvbmpeg/Makefile | 25 + .../streamdev/streamdev-cvs/libdvbmpeg/ctools.c | 2403 ++++++++++++++++++ .../streamdev/streamdev-cvs/libdvbmpeg/ctools.h | 404 +++ plugins/streamdev/streamdev-cvs/libdvbmpeg/remux.c | 1215 +++++++++ plugins/streamdev/streamdev-cvs/libdvbmpeg/remux.h | 149 ++ .../streamdev/streamdev-cvs/libdvbmpeg/ringbuffy.c | 201 ++ .../streamdev/streamdev-cvs/libdvbmpeg/ringbuffy.h | 52 + .../streamdev/streamdev-cvs/libdvbmpeg/transform.c | 2681 ++++++++++++++++++++ .../streamdev/streamdev-cvs/libdvbmpeg/transform.h | 250 ++ 13 files changed, 7394 insertions(+) create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/.cvsignore create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Entries create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Repository create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Root create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/Makefile create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/ctools.c create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/ctools.h create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/remux.c create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/remux.h create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/ringbuffy.c create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/ringbuffy.h create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/transform.c create mode 100644 plugins/streamdev/streamdev-cvs/libdvbmpeg/transform.h (limited to 'plugins/streamdev/streamdev-cvs/libdvbmpeg') diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/.cvsignore b/plugins/streamdev/streamdev-cvs/libdvbmpeg/.cvsignore new file mode 100644 index 0000000..4671378 --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/.cvsignore @@ -0,0 +1 @@ +.depend diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Entries b/plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Entries new file mode 100644 index 0000000..027b45f --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Entries @@ -0,0 +1,11 @@ +/.cvsignore/1.1.1.1/Thu Dec 30 22:44:04 2004// +/Makefile/1.3/Mon Apr 7 14:40:40 2008// +/ctools.c/1.3/Wed Mar 12 09:36:27 2008// +/ctools.h/1.1.1.1/Thu Dec 30 22:44:10 2004// +/remux.c/1.2/Fri Sep 21 11:55:56 2007// +/remux.h/1.1.1.1/Thu Dec 30 22:44:13 2004// +/ringbuffy.c/1.1.1.1/Thu Dec 30 22:44:13 2004// +/ringbuffy.h/1.1.1.1/Thu Dec 30 22:44:13 2004// +/transform.c/1.1.1.1/Thu Dec 30 22:44:17 2004// +/transform.h/1.2/Fri Jun 19 06:32:40 2009// +D diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Repository b/plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Repository new file mode 100644 index 0000000..7926483 --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Repository @@ -0,0 +1 @@ +streamdev/libdvbmpeg diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Root b/plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Root new file mode 100644 index 0000000..2c7f6ce --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/CVS/Root @@ -0,0 +1 @@ +:pserver:anoncvs@vdr-developer.org:/var/cvsroot diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/Makefile b/plugins/streamdev/streamdev-cvs/libdvbmpeg/Makefile new file mode 100644 index 0000000..a586182 --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/Makefile @@ -0,0 +1,25 @@ +INCS = -I. +CFLAGS = -g -Wall -O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -fPIC +MFLAG = -M +OBJS = ctools.o ringbuffy.o remux.o transform.o +SRC = $(wildcard *.c) + +DESTDIR = /usr/local + +.PHONY: clean + +clean: + - rm -f *.o *~ *.a .depend + +libdvbmpegtools.a: $(OBJS) + ar -rcs libdvbmpegtools.a $(OBJS) + +%.o: %.c + $(CC) -c $(CFLAGS) $(INCS) $(DEFINES) $< + +.depend: + $(CXX) $(DEFINES) $(MFLAG) $(SRC) $(INCS)> .depend + + + +-include .depend diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/ctools.c b/plugins/streamdev/streamdev-cvs/libdvbmpeg/ctools.c new file mode 100644 index 0000000..4766ea2 --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/ctools.c @@ -0,0 +1,2403 @@ +/* + * dvb-mpegtools for the Siemens Fujitsu DVB PCI card + * + * Copyright (C) 2000, 2001 Marcus Metzler + * for convergence integrated media GmbH + * Copyright (C) 2002 Marcus Metzler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + + * The author can be reached at mocm@metzlerbros.de, + */ + +#include "ctools.h" + +#define MAX_SEARCH 1024 * 1024 + + +/* + + PES + +*/ + +ssize_t save_read(int fd, void *buf, size_t count) +{ + ssize_t neof = 1; + size_t re = 0; + + while(neof >= 0 && re < count){ + neof = read(fd, buf+re, count - re); + if (neof > 0) re += neof; + else break; + } + + if (neof < 0 && re == 0) return neof; + else return re; +} + +void init_pes(pes_packet *p){ + p->stream_id = 0; + p->llength[0] = 0; + p->llength[1] = 0; + p->length = 0; + p->flags1 = 0x80; + p->flags2 = 0; + p->pes_hlength = 0; + p->trick = 0; + p->add_cpy = 0; + p->priv_flags = 0; + p->pack_field_length = 0; + p->pack_header = (uint8_t *) NULL; + p->pck_sqnc_cntr = 0; + p->org_stuff_length = 0; + p->pes_ext_lngth = 0; + p->pes_ext = (uint8_t *) NULL; + p->pes_pckt_data = (uint8_t *) NULL; + p->padding = 0; + p->mpeg = 2; // DEFAULT MPEG2 + p->mpeg1_pad = 0; + p->mpeg1_headr = NULL; + p->stuffing = 0; +} + +void kill_pes(pes_packet *p){ + if (p->pack_header) + free(p->pack_header); + if (p->pes_ext) + free(p->pes_ext); + if (p->pes_pckt_data) + free(p->pes_pckt_data); + if (p->mpeg1_headr) + free(p->mpeg1_headr); + init_pes(p); +} + +void setlength_pes(pes_packet *p){ + short *ll; + ll = (short *) p->llength; + p->length = ntohs(*ll); +} + +static void setl_pes(pes_packet *p){ + setlength_pes(p); + if (p->length) + p->pes_pckt_data = (uint8_t *)malloc(p->length); +} + +void nlength_pes(pes_packet *p){ + if (p->length <= 0xFFFF){ + short *ll = (short *) p->llength; + short l = p->length; + *ll = htons(l); + } else { + p->llength[0] =0x00; + p->llength[1] =0x00; + } +} + +static void nl_pes(pes_packet *p) +{ + nlength_pes(p); + p->pes_pckt_data = (uint8_t *) malloc(p->length); +} + +void pts2pts(uint8_t *av_pts, uint8_t *pts) +{ + + av_pts[0] = ((pts[0] & 0x06) << 5) | + ((pts[1] & 0xFC) >> 2); + av_pts[1] = ((pts[1] & 0x03) << 6) | + ((pts[2] & 0xFC) >> 2); + av_pts[2] = ((pts[2] & 0x02) << 6) | + ((pts[3] & 0xFE) >> 1); + av_pts[3] = ((pts[3] & 0x01) << 7) | + ((pts[4] & 0xFE) >> 1); + +} + + +int cwrite_pes(uint8_t *buf, pes_packet *p, long length){ + int count,i; + uint8_t dummy; + int more = 0; + uint8_t headr[3] = { 0x00, 0x00 , 0x01}; + + if (length < p->length+p->pes_hlength){ + fprintf(stderr,"Wrong buffer size in cwrite_pes\n"); + exit(1); + } + + + memcpy(buf,headr,3); + count = 3; + buf[count] = p->stream_id; + count++; + + switch ( p->stream_id ) { + + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + buf[count] = p->llength[0]; + count++; + buf[count] = p->llength[1]; + count++; + memcpy(buf+count,p->pes_pckt_data,p->length); + count += p->length; + break; + case DSM_CC_STREAM : + case ISO13522_STREAM: + case PRIVATE_STREAM1: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + buf[count] = p->llength[0]; + count++; + buf[count] = p->llength[1]; + count++; + more = 1; + break; + } + + + if ( more ) { + if ( p->mpeg == 2 ){ + memcpy(buf+count,&p->flags1,1); + count++; + memcpy(buf+count,&p->flags2,1); + count++; + memcpy(buf+count,&p->pes_hlength,1); + count++; + + if ((p->flags2 & PTS_DTS_FLAGS) == PTS_ONLY){ + memcpy(buf+count,p->pts,5); + count += 5; + } else + if ((p->flags2 & PTS_DTS_FLAGS) == PTS_DTS){ + memcpy(buf+count,p->pts,5); + count += 5; + memcpy(buf+count,p->dts,5); + count += 5; + } + if (p->flags2 & ESCR_FLAG){ + memcpy(buf+count,p->escr,6); + count += 6; + } + if (p->flags2 & ES_RATE_FLAG){ + memcpy(buf+count,p->es_rate,3); + count += 3; + } + if (p->flags2 & DSM_TRICK_FLAG){ + memcpy(buf+count,&p->trick,1); + count++; + } + if (p->flags2 & ADD_CPY_FLAG){ + memcpy(buf+count,&p->add_cpy,1); + count++; + } + if (p->flags2 & PES_CRC_FLAG){ + memcpy(buf+count,p->prev_pes_crc,2); + count += 2; + } + if (p->flags2 & PES_EXT_FLAG){ + memcpy(buf+count,&p->priv_flags,1); + count++; + + if (p->priv_flags & PRIVATE_DATA){ + memcpy(buf+count,p->pes_priv_data,16); + count += 16; + } + if (p->priv_flags & HEADER_FIELD){ + memcpy(buf+count,&p->pack_field_length, + 1); + count++; + memcpy(buf+count,p->pack_header, + p->pack_field_length); + count += p->pack_field_length; + + } + + if ( p->priv_flags & PACK_SEQ_CTR){ + memcpy(buf+count,&p->pck_sqnc_cntr,1); + count++; + memcpy(buf+count,&p->org_stuff_length, + 1); + count++; + } + + if ( p->priv_flags & P_STD_BUFFER){ + memcpy(buf+count,p->p_std,2); + count += 2; + } + if ( p->priv_flags & PES_EXT_FLAG2){ + memcpy(buf+count,&p->pes_ext_lngth,1); + count++; + memcpy(buf+count,p->pes_ext, + p->pes_ext_lngth); + count += p->pes_ext_lngth; + } + } + dummy = 0xFF; + for (i=0;istuffing;i++) { + memcpy(buf+count,&dummy,1); + count++; + } + } else { + if (p->mpeg1_pad){ + memcpy(buf+count,p->mpeg1_headr,p->mpeg1_pad); + count += p->mpeg1_pad; + } + if ((p->flags2 & PTS_DTS_FLAGS) == PTS_ONLY){ + memcpy(buf+count,p->pts,5); + count += 5; + } + else if ((p->flags2 & PTS_DTS_FLAGS) == + PTS_DTS){ + memcpy(buf+count,p->pts,5); + count += 5; + memcpy(buf+count,p->dts,5); + count += 5; + } + } + memcpy(buf+count,p->pes_pckt_data,p->length); + count += p->length; + } + + return count; + +} + +void write_pes(int fd, pes_packet *p){ + long length; + uint8_t *buf; + int l = p->length+p->pes_hlength; + + buf = (uint8_t *) malloc(l); + length = cwrite_pes(buf,p,l); + write(fd,buf,length); + free(buf); +} + +static unsigned int find_length(int f){ + uint64_t p = 0; + uint64_t start = 0; + uint64_t q = 0; + int found = 0; + uint8_t sync4[4]; + int neof = 1; + + start = lseek(f,0,SEEK_CUR); + start -=2; + lseek(f,start,SEEK_SET); + while ( neof > 0 && !found ){ + p = lseek(f,0,SEEK_CUR); + neof = save_read(f,&sync4,4); + if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) { + switch ( sync4[3] ) { + + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + case PRIVATE_STREAM1: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + found = 1; + break; + default: + q = lseek(f,0,SEEK_CUR); + break; + } + } + } + q = lseek(f,0,SEEK_CUR); + lseek(f,start+2,SEEK_SET); + if (found) return (unsigned int)(q-start)-4-2; + else return (unsigned int)(q-start-2); + +} + + +void cread_pes(char *buf, pes_packet *p){ + + uint8_t count, dummy, check; + int i; + uint64_t po = 0; + int c=0; + + switch ( p->stream_id ) { + + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + memcpy(p->pes_pckt_data,buf+c,p->length); + return; + break; + case PADDING_STREAM : + p->padding = p->length; + memcpy(p->pes_pckt_data,buf+c,p->length); + return; + break; + case DSM_CC_STREAM : + case ISO13522_STREAM: + case PRIVATE_STREAM1: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + break; + default: + return; + break; + } + + po = c; + memcpy(&p->flags1,buf+c,1); + c++; + if ( (p->flags1 & 0xC0) == 0x80 ) p->mpeg = 2; + else p->mpeg = 1; + + if ( p->mpeg == 2 ){ + memcpy(&p->flags2,buf+c,1); + c++; + memcpy(&p->pes_hlength,buf+c,1); + c++; + + p->length -=p->pes_hlength+3; + count = p->pes_hlength; + + if ((p->flags2 & PTS_DTS_FLAGS) == PTS_ONLY){ + memcpy(p->pts,buf+c,5); + c += 5; + count -=5; + } else + if ((p->flags2 & PTS_DTS_FLAGS) == PTS_DTS){ + memcpy(p->pts,buf+c,5); + c += 5; + memcpy(p->dts,buf+c,5); + c += 5; + count -= 10; + } + + if (p->flags2 & ESCR_FLAG){ + memcpy(p->escr,buf+c,6); + c += 6; + count -= 6; + } + + if (p->flags2 & ES_RATE_FLAG){ + memcpy(p->es_rate,buf+c,3); + c += 3; + count -= 3; + } + + if (p->flags2 & DSM_TRICK_FLAG){ + memcpy(&p->trick,buf+c,1); + c += 1; + count -= 1; + } + + if (p->flags2 & ADD_CPY_FLAG){ + memcpy(&p->add_cpy,buf+c,1); + c++; + count -= 1; + } + + if (p->flags2 & PES_CRC_FLAG){ + memcpy(p->prev_pes_crc,buf+c,2); + c += 2; + count -= 2; + } + + if (p->flags2 & PES_EXT_FLAG){ + memcpy(&p->priv_flags,buf+c,1); + c++; + count -= 1; + + if (p->priv_flags & PRIVATE_DATA){ + memcpy(p->pes_priv_data,buf+c,16); + c += 16; + count -= 16; + } + + if (p->priv_flags & HEADER_FIELD){ + memcpy(&p->pack_field_length,buf+c,1); + c++; + p->pack_header = (uint8_t *) + malloc(p->pack_field_length); + memcpy(p->pack_header,buf+c, + p->pack_field_length); + c += p->pack_field_length; + count -= 1+p->pack_field_length; + } + + if ( p->priv_flags & PACK_SEQ_CTR){ + memcpy(&p->pck_sqnc_cntr,buf+c,1); + c++; + memcpy(&p->org_stuff_length,buf+c,1); + c++; + count -= 2; + } + + if ( p->priv_flags & P_STD_BUFFER){ + memcpy(p->p_std,buf+c,2); + c += 2; + count -= 2; + } + + if ( p->priv_flags & PES_EXT_FLAG2){ + memcpy(&p->pes_ext_lngth,buf+c,1); + c++; + p->pes_ext = (uint8_t *) + malloc(p->pes_ext_lngth); + memcpy(p->pes_ext,buf+c, + p->pes_ext_lngth); + c += p->pes_ext_lngth; + count -= 1+p->pes_ext_lngth; + } + } + p->stuffing = count; + for(i = 0; i< count ;i++){ + memcpy(&dummy,buf+c,1); + c++; + } + } else { + p->mpeg1_pad = 1; + check = p->flags1; + while (check == 0xFF){ + memcpy(&check,buf+c,1); + c++; + p->mpeg1_pad++; + } + + if ( (check & 0xC0) == 0x40){ + memcpy(&check,buf+c,1); + c++; + p->mpeg1_pad++; + memcpy(&check,buf+c,1); + c++; + p->mpeg1_pad++; + } + p->flags2 = 0; + p->length -= p->mpeg1_pad; + + c = po; + if ( (check & 0x30)){ + p->length ++; + p->mpeg1_pad --; + + if (check == p->flags1){ + p->pes_hlength = 0; + } else { + p->mpeg1_headr = (uint8_t *) + malloc(p->mpeg1_pad); + p->pes_hlength = p->mpeg1_pad; + memcpy(p->mpeg1_headr,buf+c, + p->mpeg1_pad); + c += p->mpeg1_pad; + } + + p->flags2 = (check & 0xF0) << 2; + if ((p->flags2 & PTS_DTS_FLAGS) == PTS_ONLY){ + memcpy(p->pts,buf+c,5); + c += 5; + p->length -= 5; + p->pes_hlength += 5; + } + else if ((p->flags2 & PTS_DTS_FLAGS) == + PTS_DTS){ + memcpy(p->pts,buf+c,5); + c += 5; + memcpy(p->dts,buf+c,5); + c += 5; + p->length -= 10; + p->pes_hlength += 10; + } + } else { + p->mpeg1_headr = (uint8_t *) malloc(p->mpeg1_pad); + p->pes_hlength = p->mpeg1_pad; + memcpy(p->mpeg1_headr,buf+c, + p->mpeg1_pad); + c += p->mpeg1_pad; + } + } + memcpy(p->pes_pckt_data,buf+c,p->length); +} + + +int read_pes(int f, pes_packet *p){ + + uint8_t sync4[4]; + int found=0; + uint64_t po = 0; + int neof = 1; + uint8_t *buf; + + while (neof > 0 && !found) { + po = lseek(f,0,SEEK_CUR); + if (po < 0) return -1; + if ((neof = save_read(f,&sync4,4)) < 4) return -1; + if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) { + p->stream_id = sync4[3]; + switch ( sync4[3] ) { + + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + case PRIVATE_STREAM1: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + if((neof = save_read(f,p->llength,2)) < 2) + return -1; + setl_pes(p); + if (!p->length){ + p->length = find_length(f); + nl_pes(p); + } + found = 1; + break; + + default: + if (lseek(f,po+1,SEEK_SET) < po+1) return -1; + break; + } + } else if(lseek(f,po+1,SEEK_SET) < po+1) return -1; + } + + if (!found || !p->length) return 0; + + if (p->length >0){ + buf = (uint8_t *) malloc(p->length); + if((neof = save_read(f,buf,p->length))< p->length) return -1; + cread_pes((char *)buf,p); + free(buf); + } else return 0; + + return neof; +} + +/* + + Transport Stream + +*/ + +void init_ts(ts_packet *p){ + p->pid[0] = 0; + p->pid[1] = 0; + p->flags = 0; + p->count = 0; + p->adapt_length = 0; + p->adapt_flags = 0; + p->splice_count = 0; + p->priv_dat_len = 0; + p->priv_dat = NULL; + p->adapt_ext_len = 0; + p->adapt_eflags = 0; + p->rest = 0; + p->stuffing = 0; +} + +void kill_ts(ts_packet *p){ + if (p->priv_dat) + free(p->priv_dat); + init_ts(p); +} + + + +unsigned short pid_ts(ts_packet *p) +{ + return get_pid(p->pid); +} + +int cwrite_ts(uint8_t *buf, ts_packet *p, long length){ + long count,i; + uint8_t sync,dummy; + + sync = 0x47; + memcpy(buf,&sync,1); + count = 1; + memcpy(buf+count,p->pid,2); + count += 2; + memcpy(buf+count,&p->flags,1); + count++; + + + if (! (p->flags & ADAPT_FIELD) && (p->flags & PAYLOAD)){ + memcpy(buf+count,p->data,184); + count += 184; + } else { + memcpy(buf+count,&p->adapt_length,1); + count++; + memcpy(buf+count,&p->adapt_flags,1); + count++; + + if ( p->adapt_flags & PCR_FLAG ){ + memcpy(buf+count, p->pcr,6); + count += 6; + } + if ( p->adapt_flags & OPCR_FLAG ){ + memcpy(buf+count, p->opcr,6); + count += 6; + } + if ( p->adapt_flags & SPLICE_FLAG ){ + memcpy(buf+count, &p->splice_count,1); + count++; + } + if( p->adapt_flags & TRANS_PRIV){ + memcpy(buf+count,&p->priv_dat_len,1); + count++; + memcpy(buf+count,p->priv_dat,p->priv_dat_len); + count += p->priv_dat_len; + } + + if( p->adapt_flags & ADAP_EXT_FLAG){ + memcpy(buf+count,&p->adapt_ext_len,1); + count++; + memcpy(buf+count,&p->adapt_eflags,1); + count++; + + if( p->adapt_eflags & LTW_FLAG){ + memcpy(buf+count,p->ltw,2); + count += 2; + } + if( p->adapt_eflags & PIECE_RATE){ + memcpy(buf+count,p->piece_rate,3); + count += 3; + } + if( p->adapt_eflags & SEAM_SPLICE){ + memcpy(buf+count,p->dts,5); + count += 5; + } + } + dummy = 0xFF; + for(i=0; i < p->stuffing ; i++){ + memcpy(buf+count,&dummy,1); + count++; + } + if (p->flags & PAYLOAD){ + memcpy(buf+count,p->data,p->rest); + count += p->rest; + } + } + + + return count; +} + +void write_ts(int fd, ts_packet *p){ + long length; + uint8_t buf[TS_SIZE]; + + length = cwrite_ts(buf,p,TS_SIZE); + write(fd,buf,length); +} + +int read_ts (int f, ts_packet *p){ + uint8_t sync; + int found=0; + uint64_t po,q; + int neof = 1; + + sync=0; + while (neof > 0 && !found) { + neof = save_read(f,&sync,1); + if (sync == 0x47) + found = 1; + } + neof = save_read(f,p->pid,2); + neof = save_read(f,&p->flags,1); + p->count = p->flags & COUNT_MASK; + + if (!(p->flags & ADAPT_FIELD) && (p->flags & PAYLOAD)){ + //no adapt. field only payload + neof = save_read(f,p->data,184); + p->rest = 184; + return neof; + } + + if ( p->flags & ADAPT_FIELD ) { + // adaption field + neof = save_read(f,&p->adapt_length,1); + po = lseek(f,0,SEEK_CUR); + neof = save_read(f,&p->adapt_flags,1); + + if ( p->adapt_flags & PCR_FLAG ) + neof = save_read(f, p->pcr,6); + + if ( p->adapt_flags & OPCR_FLAG ) + neof = save_read(f, p->opcr,6); + + if ( p->adapt_flags & SPLICE_FLAG ) + neof = save_read(f, &p->splice_count,1); + + if( p->adapt_flags & TRANS_PRIV){ + neof = save_read(f,&p->priv_dat_len,1); + p->priv_dat = (uint8_t *) malloc(p->priv_dat_len); + neof = save_read(f,p->priv_dat,p->priv_dat_len); + } + + if( p->adapt_flags & ADAP_EXT_FLAG){ + neof = save_read(f,&p->adapt_ext_len,1); + neof = save_read(f,&p->adapt_eflags,1); + if( p->adapt_eflags & LTW_FLAG) + neof = save_read(f,p->ltw,2); + + if( p->adapt_eflags & PIECE_RATE) + neof = save_read(f,p->piece_rate,3); + + if( p->adapt_eflags & SEAM_SPLICE) + neof = save_read(f,p->dts,5); + } + q = lseek(f,0,SEEK_CUR); + p->stuffing = p->adapt_length -(q-po); + p->rest = 183-p->adapt_length; + lseek(f,q+p->stuffing,SEEK_SET); + if (p->flags & PAYLOAD) // payload + neof = save_read(f,p->data,p->rest); + else + lseek(f,q+p->rest,SEEK_SET); + } + return neof; +} + +void cread_ts (char *buf, ts_packet *p, long length){ + uint8_t sync; + int found=0; + uint64_t po,q; + long count=0; + + sync=0; + while (count < length && !found) { + sync=buf[count]; + count++; + if (sync == 0x47) + found = 1; + } + memcpy(p->pid,buf+count,2); + count += 2; + p->flags = buf[count]; + count++; + p->count = p->flags & COUNT_MASK; + + if (!(p->flags & ADAPT_FIELD) && (p->flags & PAYLOAD)){ + //no adapt. field only payload + memcpy(p->data,buf+count,184); + p->rest = 184; + return; + } + + if ( p->flags & ADAPT_FIELD ) { + // adaption field + p->adapt_length = buf[count]; + count++; + po = count; + memcpy(&p->adapt_flags,buf+count,1); + count++; + + if ( p->adapt_flags & PCR_FLAG ){ + memcpy( p->pcr,buf+count,6); + count += 6; + } + if ( p->adapt_flags & OPCR_FLAG ){ + memcpy( p->opcr,buf+count,6); + count += 6; + } + if ( p->adapt_flags & SPLICE_FLAG ){ + memcpy( &p->splice_count,buf+count,1); + count++; + } + if( p->adapt_flags & TRANS_PRIV){ + memcpy(&p->priv_dat_len,buf+count,1); + count++; + p->priv_dat = (uint8_t *) malloc(p->priv_dat_len); + memcpy(p->priv_dat,buf+count,p->priv_dat_len); + count += p->priv_dat_len; + } + + if( p->adapt_flags & ADAP_EXT_FLAG){ + memcpy(&p->adapt_ext_len,buf+count,1); + count++; + memcpy(&p->adapt_eflags,buf+count,1); + count++; + if( p->adapt_eflags & LTW_FLAG){ + memcpy(p->ltw,buf+count,2); + count += 2; + } + if( p->adapt_eflags & PIECE_RATE){ + memcpy(p->piece_rate,buf+count,3); + count += 3; + } + if( p->adapt_eflags & SEAM_SPLICE){ + memcpy(p->dts,buf+count,5); + count += 5; + } + } + q = count; + p->stuffing = p->adapt_length -(q-po); + p->rest = 183-p->adapt_length; + count = q+p->stuffing; + if (p->flags & PAYLOAD){ // payload + memcpy(p->data,buf+count,p->rest); + count += p->rest; + } else + count = q+p->rest; + } +} + + +/* + + Program Stream + +*/ + + +void init_ps(ps_packet *p) +{ + p->stuff_length=0xF8; + p->data = NULL; + p->sheader_length = 0; + p->audio_bound = 0; + p->video_bound = 0; + p->npes = 0; + p->mpeg = 2; +} + +void kill_ps(ps_packet *p) +{ + if (p->data) + free(p->data); + init_ps(p); +} + +void setlength_ps(ps_packet *p) +{ + short *ll; + ll = (short *) p->sheader_llength; + if (p->mpeg == 2) + p->sheader_length = ntohs(*ll) - 6; + else + p->sheader_length = ntohs(*ll); +} + +static void setl_ps(ps_packet *p) +{ + setlength_ps(p); + p->data = (uint8_t *) malloc(p->sheader_length); +} + +int mux_ps(ps_packet *p) +{ + uint32_t mux = 0; + uint8_t *i = (uint8_t *)&mux; + + i[1] = p->mux_rate[0]; + i[2] = p->mux_rate[1]; + i[3] = p->mux_rate[2]; + mux = ntohl(mux); + mux = (mux >>2); + return mux; +} + +int rate_ps(ps_packet *p) +{ + uint32_t rate=0; + uint8_t *i= (uint8_t *) &rate; + + i[1] = p->rate_bound[0] & 0x7F; + i[2] = p->rate_bound[1]; + i[3] = p->rate_bound[2]; + + rate = ntohl(rate); + rate = (rate >> 1); + return rate; +} + + +uint32_t scr_base_ps(ps_packet *p) // only 32 bit!! +{ + uint32_t base = 0; + uint8_t *buf = (uint8_t *)&base; + + buf[0] |= (long int)((p->scr[0] & 0x18) << 3); + buf[0] |= (long int)((p->scr[0] & 0x03) << 4); + buf[0] |= (long int)((p->scr[1] & 0xF0) >> 4); + + buf[1] |= (long int)((p->scr[1] & 0x0F) << 4); + buf[1] |= (long int)((p->scr[2] & 0xF0) >> 4); + + buf[2] |= (long int)((p->scr[2] & 0x08) << 4); + buf[2] |= (long int)((p->scr[2] & 0x03) << 5); + buf[2] |= (long int)((p->scr[3] & 0xF8) >> 3); + + buf[3] |= (long int)((p->scr[3] & 0x07) << 5); + buf[3] |= (long int)((p->scr[4] & 0xF8) >> 3); + + base = ntohl(base); + return base; +} + +uint16_t scr_ext_ps(ps_packet *p) +{ + short ext = 0; + + ext = (short)(p->scr[5] >> 1); + ext += (short) (p->scr[4] & 0x03) * 128; + + return ext; +} + +int cwrite_ps(uint8_t *buf, ps_packet *p, long length) +{ + long count,i; + uint8_t headr1[4] = {0x00, 0x00, 0x01, 0xBA }; + uint8_t headr2[4] = {0x00, 0x00, 0x01, 0xBB }; + uint8_t buffy = 0xFF; + + + memcpy(buf,headr1,4); + count = 4; + if (p->mpeg == 2){ + memcpy(buf+count,p->scr,6); + count += 6; + memcpy(buf+count,p->mux_rate,3); + count += 3; + memcpy(buf+count,&p->stuff_length,1); + count++; + for(i=0; i< (p->stuff_length & 3); i++){ + memcpy(buf+count,&buffy,1); + count++; + } + } else { + memcpy(buf+count,p->scr,5); + count += 5; + memcpy(buf+count,p->mux_rate,3); + count += 3; + } + if (p->sheader_length){ + memcpy(buf+count,headr2,4); + count += 4; + memcpy(buf+count,p->sheader_llength,2); + count += 2; + if ( p->mpeg == 2){ + memcpy(buf+count,p->rate_bound,3); + count += 3; + memcpy(buf+count,&p->audio_bound,1); + count++; + memcpy(buf+count,&p->video_bound,1); + count++; + memcpy(buf+count,&p->reserved,1); + count++; + } + memcpy(buf+count,p->data,p->sheader_length); + count += p->sheader_length; + } + + return count; +} + +void write_ps(int fd, ps_packet *p){ + long length; + uint8_t buf[PS_MAX]; + + length = cwrite_ps(buf,p,PS_MAX); + write(fd,buf,length); +} + +int read_ps (int f, ps_packet *p){ + uint8_t headr[4]; + pes_packet pes; + int i,done; + int found=0; + uint64_t po = 0; + uint64_t q = 0; + long count = 0; + int neof = 1; + + po = lseek(f,0,SEEK_CUR); + while (neof > 0 && !found && count < MAX_SEARCH) { + neof = save_read(f,&headr,4); + if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01){ + if ( headr[3] == 0xBA ) + found = 1; + else + if ( headr[3] == 0xB9 ) break; + else lseek(f,po+1,SEEK_SET); + } + count++; + } + + if (found){ + neof = save_read(f,p->scr,6); + if (p->scr[0] & 0x40) + p->mpeg = 2; + else + p->mpeg = 1; + + if (p->mpeg == 2){ + neof = save_read(f,p->mux_rate,3); + neof = save_read(f,&p->stuff_length,1); + po = lseek(f,0,SEEK_CUR); + lseek(f,po+(p->stuff_length & 3),SEEK_SET); + } else { + p->mux_rate[0] = p->scr[5]; //mpeg1 scr is only 5 bytes + neof = save_read(f,p->mux_rate+1,2); + } + + po = lseek(f,0,SEEK_CUR); + neof = save_read(f,headr,4); + if (headr[0] == 0x00 && headr[1] == 0x00 && + headr[2] == 0x01 && headr[3] == 0xBB ) { + neof = save_read(f,p->sheader_llength,2); + setl_ps(p); + if (p->mpeg == 2){ + neof = save_read(f,p->rate_bound,3); + neof = save_read(f,&p->audio_bound,1); + neof = save_read(f,&p->video_bound,1); + neof = save_read(f,&p->reserved,1); + } + neof = save_read(f,p->data,p->sheader_length); + } else { + lseek(f,po,SEEK_SET); + p->sheader_length = 0; + } + + i = 0; + done = 0; + q = lseek(f,0,SEEK_CUR); + do { + po = lseek(f,0,SEEK_CUR); + neof = save_read(f,headr,4); + lseek(f,po,SEEK_SET); + if ( headr[0] == 0x00 && headr[1] == 0x00 + && headr[2] == 0x01 && headr[3] != 0xBA){ + init_pes(&pes); + neof = read_pes(f,&pes); + i++; + } else done = 1; + kill_pes(&pes); + } while ( neof > 0 && !done); + p->npes = i; + lseek(f,q,SEEK_SET); + } + return neof; +} + +void cread_ps (char *buf, ps_packet *p, long length){ + uint8_t *headr; + pes_packet pes; + int i,done; + int found=0; + uint64_t po = 0; + uint64_t q = 0; + long count = 0; + long c = 0; + + po = c; + while ( count < length && !found && count < MAX_SEARCH) { + headr = (uint8_t *)buf+c; + c += 4; + if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01){ + if ( headr[3] == 0xBA ) + found = 1; + else + if ( headr[3] == 0xB9 ) break; + else c = po+1; + } + count++; + } + + if (found){ + memcpy(p->scr,buf+c,6); + c += 6; + if (p->scr[0] & 0x40) + p->mpeg = 2; + else + p->mpeg = 1; + + if (p->mpeg == 2){ + memcpy(p->mux_rate,buf+c,3); + c += 3; + memcpy(&p->stuff_length,buf+c,1); + c++; + po = c; + c = po+(p->stuff_length & 3); + } else { + p->mux_rate[0] = p->scr[5]; //mpeg1 scr is only 5 bytes + memcpy(p->mux_rate+1,buf+c,2); + c += 2; + } + + po = c; + headr = (uint8_t *)buf+c; + c += 4; + if (headr[0] == 0x00 && headr[1] == 0x00 && + headr[2] == 0x01 && headr[3] == 0xBB ) { + memcpy(p->sheader_llength,buf+c,2); + c += 2; + setl_ps(p); + if (p->mpeg == 2){ + memcpy(p->rate_bound,buf+c,3); + c += 3; + memcpy(&p->audio_bound,buf+c,1); + c++; + memcpy(&p->video_bound,buf+c,1); + c++; + memcpy(&p->reserved,buf+c,1); + c++; + } + memcpy(p->data,buf+c,p->sheader_length); + c += p->sheader_length; + } else { + c = po; + p->sheader_length = 0; + } + + i = 0; + done = 0; + q = c; + do { + headr = (uint8_t *)buf+c; + if ( headr[0] == 0x00 && headr[1] == 0x00 + && headr[2] == 0x01 && headr[3] != 0xBA){ + init_pes(&pes); + // cread_pes(buf+c,&pes); + i++; + } else done = 1; + kill_pes(&pes); + } while (c < length && !done); + p->npes = i; + c = q; + } +} + + + + + + + +/* + conversion +*/ + +void init_trans(trans *p) +{ + int i; + + p->found = 0; + p->pes = 0; + p->is_full = 0; + p->pes_start = 0; + p->pes_started = 0; + p->set = 0; + + for (i = 0; i < MASKL*MAXFILT ; i++){ + p->mask[i] = 0; + p->filt[i] = 0; + } + for (i = 0; i < MAXFILT ; i++){ + p->sec[i].found = 0; + p->sec[i].length = 0; + } +} + +int set_trans_filt(trans *p, int filtn, uint16_t pid, uint8_t *mask, uint8_t *filt, int pes) +{ + int i; + int off; + + if ( filtn > MAXFILT-1 || filtn<0 ) return -1; + p->pid[filtn] = pid; + if (pes) p->pes |= (tflags)(1 << filtn); + else { + off = MASKL*filtn; + p->pes &= ~((tflags) (1 << filtn) ); + for (i = 0; i < MASKL ; i++){ + p->mask[off+i] = mask[i]; + p->filt[off+i] = filt[i]; + } + } + p->set |= (tflags) (1 << filtn); + return 0; +} + +void clear_trans_filt(trans *p,int filtn) +{ + int i; + + p->set &= ~((tflags) (1 << filtn) ); + p->pes &= ~((tflags) (1 << filtn) ); + p->is_full &= ~((tflags) (1 << filtn) ); + p->pes_start &= ~((tflags) (1 << filtn) ); + p->pes_started &= ~((tflags) (1 << filtn) ); + + for (i = MASKL*filtn; i < MASKL*(filtn+1) ; i++){ + p->mask[i] = 0; + p->filt[i] = 0; + } + p->sec[filtn].found = 0; + p->sec[filtn].length = 0; +} + +int filt_is_set(trans *p, int filtn) +{ + if (p->set & ((tflags)(1 << filtn))) return 1; + return 0; +} + +int pes_is_set(trans *p, int filtn) +{ + if (p->pes & ((tflags)(1 << filtn))) return 1; + return 0; +} + +int pes_is_started(trans *p, int filtn) +{ + if (p->pes_started & ((tflags)(1 << filtn))) return 1; + return 0; +} + +int pes_is_start(trans *p, int filtn) +{ + if (p->pes_start & ((tflags)(1 << filtn))) return 1; + return 0; +} + +int filt_is_ready(trans *p,int filtn) +{ + if (p->is_full & ((tflags)(1 << filtn))) return 1; + return 0; +} + +void trans_filt(uint8_t *buf, int count, trans *p) +{ + int c=0; + //fprintf(stderr,"trans_filt\n"); + + + while (c < count && p->found <1 ){ + if ( buf[c] == 0x47) p->found = 1; + c++; + p->packet[0] = 0x47; + } + if (c == count) return; + + while( c < count && p->found < 188 && p->found > 0 ){ + p->packet[p->found] = buf[c]; + c++; + p->found++; + } + if (p->found == 188){ + p->found = 0; + tfilter(p); + } + + if (c < count) trans_filt(buf+c,count-c,p); +} + + +void tfilter(trans *p) +{ + int l,c; + int tpid; + uint8_t flag,flags; + uint8_t adapt_length = 0; + uint8_t cpid[2]; + + + // fprintf(stderr,"tfilter\n"); + + cpid[0] = p->packet[1]; + cpid[1] = p->packet[2]; + tpid = get_pid(cpid); + + if ( p->packet[1]&0x80){ + fprintf(stderr,"Error in TS for PID: %d\n", + tpid); + } + + flag = cpid[0]; + flags = p->packet[3]; + + if ( flags & ADAPT_FIELD ) { + // adaption field + adapt_length = p->packet[4]; + } + + c = 5 + adapt_length - (int)(!(flags & ADAPT_FIELD)); + if (flags & PAYLOAD){ + for ( l = 0; l < MAXFILT ; l++){ + if ( filt_is_set(p,l) ) { + if ( p->pid[l] == tpid) { + if ( pes_is_set(p,l) ){ + if (cpid[0] & PAY_START){ + p->pes_started |= + (tflags) + (1 << l); + p->pes_start |= + (tflags) + (1 << l); + } else { + p->pes_start &= ~ + ((tflags) + (1 << l)); + } + pes_filter(p,l,c); + } else { + sec_filter(p,l,c); + } + } + } + } + } +} + + +void pes_filter(trans *p, int filtn, int off) +{ + int count,c; + uint8_t *buf; + + if (filtn < 0 || filtn >= MAXFILT) return; + + count = 188 - off; + c = 188*filtn; + buf = p->packet+off; + if (pes_is_started(p,filtn)){ + p->is_full |= (tflags) (1 << filtn); + memcpy(p->transbuf+c,buf,count); + p->transcount[filtn] = count; + } +} + +section *get_filt_sec(trans *p, int filtn) +{ + section *sec; + + sec = &p->sec[filtn]; + p->is_full &= ~((tflags) (1 << filtn) ); + return sec; +} + +int get_filt_buf(trans *p, int filtn,uint8_t **buf) +{ + *buf = p->transbuf+188*filtn; + p->is_full &= ~((tflags) (1 << filtn) ); + return p->transcount[filtn]; +} + + + + +void sec_filter(trans *p, int filtn, int off) +{ + int i,j; + int error; + int count,c; + uint8_t *buf, *secbuf; + section *sec; + + // fprintf(stderr,"sec_filter\n"); + + if (filtn < 0 || filtn >= MAXFILT) return; + + count = 188 - off; + c = 0; + buf = p->packet+off; + sec = &p->sec[filtn]; + secbuf = sec->payload; + if(!filt_is_ready(p,filtn)){ + p->is_full &= ~((tflags) (1 << filtn) ); + sec->found = 0; + sec->length = 0; + } + + if ( !sec->found ){ + c = buf[c]+1; + if (c >= count) return; + sec->id = buf[c]; + secbuf[0] = buf[c]; + c++; + sec->found++; + sec->length = 0; + } + + while ( c < count && sec->found < 3){ + secbuf[sec->found] = buf[c]; + c++; + sec->found++; + } + if (c == count) return; + + if (!sec->length && sec->found == 3){ + sec->length |= ((secbuf[1] & 0x0F) << 8); + sec->length |= (secbuf[2] & 0xFF); + } + + while ( c < count && sec->found < sec->length+3){ + secbuf[sec->found] = buf[c]; + c++; + sec->found++; + } + + if ( sec->length && sec->found == sec->length+3 ){ + error=0; + for ( i = 0; i < MASKL; i++){ + if (i > 0 ) j=2+i; + else j = 0; + error += (sec->payload[j]&p->mask[MASKL*filtn+i])^ + (p->filt[MASKL*filtn+i]& + p->mask[MASKL*filtn+i]); + } + if (!error){ + p->is_full |= (tflags) (1 << filtn); + } + if (buf[0]+1 < c ) c=count; + } + + if ( c < count ) sec_filter(p, filtn, off); + +} + +#define MULT 1024 + + +void write_ps_headr( ps_packet *p, uint8_t *pts,int fd) +{ + long muxr = 37500; + uint8_t audio_bound = 1; + uint8_t fixed = 0; + uint8_t CSPS = 0; + uint8_t audio_lock = 1; + uint8_t video_lock = 1; + uint8_t video_bound = 1; + uint8_t stream1 = 0XC0; + uint8_t buffer1_scale = 1; + uint32_t buffer1_size = 32; + uint8_t stream2 = 0xE0; + uint8_t buffer2_scale = 1; + uint32_t buffer2_size = 230; + + init_ps(p); + + p->mpeg = 2; +// SCR = 0 + p->scr[0] = 0x44; + p->scr[1] = 0x00; + p->scr[2] = 0x04; + p->scr[3] = 0x00; + p->scr[4] = 0x04; + p->scr[5] = 0x01; + +// SCR = PTS + p->scr[0] = 0x44 | ((pts[0] >> 3)&0x18) | ((pts[0] >> 4)&0x03); + p->scr[1] = 0x00 | ((pts[0] << 4)&0xF0) | ((pts[1] >> 4)&0x0F); + p->scr[2] = 0x04 | ((pts[1] << 4)&0xF0) | ((pts[2] >> 4)&0x08) + | ((pts[2] >> 5)&0x03); + p->scr[3] = 0x00 | ((pts[2] << 3)&0xF8) | ((pts[3] >> 5)&0x07); + p->scr[4] = 0x04 | ((pts[3] << 3)&0xF8); + p->scr[5] = 0x01; + + p->mux_rate[0] = (uint8_t)(muxr >> 14); + p->mux_rate[1] = (uint8_t)(0xff & (muxr >> 6)); + p->mux_rate[2] = (uint8_t)(0x03 | ((muxr & 0x3f) << 2)); + + p->stuff_length = 0xF8; + + p->sheader_llength[0] = 0x00; + p->sheader_llength[1] = 0x0c; + + setl_ps(p); + + p->rate_bound[0] = (uint8_t)(0x80 | (muxr >>15)); + p->rate_bound[1] = (uint8_t)(0xff & (muxr >> 7)); + p->rate_bound[2] = (uint8_t)(0x01 | ((muxr & 0x7f)<<1)); + + + p->audio_bound = (uint8_t)((audio_bound << 2)|(fixed << 1)|CSPS); + p->video_bound = (uint8_t)((audio_lock << 7)| + (video_lock << 6)|0x20|video_bound); + p->reserved = (uint8_t)(0xFF); + + p->data[0] = stream2; + p->data[1] = (uint8_t) (0xc0 | (buffer2_scale << 5) | + (buffer2_size >> 8)); + p->data[2] = (uint8_t) (buffer2_size & 0xff); + p->data[3] = stream1; + p->data[4] = (uint8_t) (0xc0 | (buffer1_scale << 5) | + (buffer1_size >> 8)); + p->data[5] = (uint8_t) (buffer1_size & 0xff); + + write_ps(fd, p); + kill_ps(p); +} + + + +void twrite(uint8_t const *buf) +{ + int l = TS_SIZE; + int c = 0; + int w; + + + while (l){ + w = write(STDOUT_FILENO,buf+c,l); + if (w>=0){ + l-=w; + c+=w; + } + } +} + +void init_p2t(p2t_t *p, void (*fkt)(uint8_t const *buf)) +{ + memset(p->pes,0,TS_SIZE); + p->counter = 0; + p->pos = 0; + p->frags = 0; + if (fkt) p->t_out = fkt; + else p->t_out = twrite; +} + +void clear_p2t(p2t_t *p) +{ + memset(p->pes,0,TS_SIZE); + p->counter = 0; + p->pos = 0; + p->frags = 0; +} + + +long int find_pes_header(uint8_t const *buf, long int length, int *frags) +{ + int c = 0; + int found = 0; + + *frags = 0; + + while (c < length-3 && !found) { + if (buf[c] == 0x00 && buf[c+1] == 0x00 && + buf[c+2] == 0x01) { + switch ( buf[c+3] ) { + case 0xBA: + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + case PRIVATE_STREAM1: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + found = 1; + break; + + default: + c++; + break; + } + } else c++; + } + if (c == length-3 && !found){ + if (buf[length-1] == 0x00) *frags = 1; + if (buf[length-2] == 0x00 && + buf[length-1] == 0x00) *frags = 2; + if (buf[length-3] == 0x00 && + buf[length-2] == 0x00 && + buf[length-1] == 0x01) *frags = 3; + return -1; + } + + return c; +} + +void pes_to_ts( uint8_t const *buf, long int length, uint16_t pid, p2t_t *p) +{ + int c,c2,l,add; + int check,rest; + + c = 0; + c2 = 0; + if (p->frags){ + check = 0; + switch(p->frags){ + case 1: + if ( buf[c] == 0x00 && buf[c+1] == 0x01 ){ + check = 1; + c += 2; + } + break; + case 2: + if ( buf[c] == 0x01 ){ + check = 1; + c++; + } + break; + case 3: + check = 1; + } + if(check){ + switch ( buf[c] ) { + + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + case PRIVATE_STREAM1: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + p->pes[0] = 0x00; + p->pes[1] = 0x00; + p->pes[2] = 0x01; + p->pes[3] = buf[c]; + p->pos=4; + memcpy(p->pes+p->pos,buf+c,TS_SIZE-4-p->pos); + c += TS_SIZE-4-p->pos; + p_to_t(p->pes,TS_SIZE-4,pid,&p->counter, + p->t_out); + clear_p2t(p); + break; + + default: + c=0; + break; + } + } + p->frags = 0; + } + + if (p->pos){ + c2 = find_pes_header(buf+c,length-c,&p->frags); + if (c2 >= 0 && c2 < TS_SIZE-4-p->pos){ + l = c2+c; + } else l = TS_SIZE-4-p->pos; + memcpy(p->pes+p->pos,buf,l); + c += l; + p->pos += l; + p_to_t(p->pes,p->pos,pid,&p->counter, + p->t_out); + clear_p2t(p); + } + + add = 0; + while (c < length){ + c2 = find_pes_header(buf+c+add,length-c-add,&p->frags); + if (c2 >= 0) { + c2 += c+add; + if (c2 > c){ + p_to_t(buf+c,c2-c,pid,&p->counter, + p->t_out); + c = c2; + clear_p2t(p); + add = 0; + } else add = 1; + } else { + l = length-c; + rest = l % (TS_SIZE-4); + l -= rest; + p_to_t(buf+c,l,pid,&p->counter, + p->t_out); + memcpy(p->pes,buf+c+l,rest); + p->pos = rest; + c = length; + } + } +} + + + +void p_to_t( uint8_t const *buf, long int length, uint16_t pid, uint8_t *counter, + void (*ts_write)(uint8_t const *)) +{ + + int l, pes_start; + uint8_t obuf[TS_SIZE]; + long int c = 0; + pes_start = 0; + if ( length > 3 && + buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01 ) + switch (buf[3]){ + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + case PRIVATE_STREAM1: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + pes_start = 1; + break; + + default: + break; + } + + while ( c < length ){ + memset(obuf,0,TS_SIZE); + if (length - c >= TS_SIZE-4){ + l = write_ts_header(pid, counter, pes_start + , obuf, TS_SIZE-4); + memcpy(obuf+l, buf+c, TS_SIZE-l); + c += TS_SIZE-l; + } else { + l = write_ts_header(pid, counter, pes_start + , obuf, length-c); + memcpy(obuf+l, buf+c, TS_SIZE-l); + c = length; + } + ts_write(obuf); + pes_start = 0; + } +} + + +int write_ps_header(uint8_t *buf, + uint32_t SCR, + long muxr, + uint8_t audio_bound, + uint8_t fixed, + uint8_t CSPS, + uint8_t audio_lock, + uint8_t video_lock, + uint8_t video_bound, + uint8_t stream1, + uint8_t buffer1_scale, + uint32_t buffer1_size, + uint8_t stream2, + uint8_t buffer2_scale, + uint32_t buffer2_size) +{ + ps_packet p; + uint8_t *pts; + long lpts; + init_ps(&p); + + lpts = htonl(SCR); + pts = (uint8_t *) &lpts; + + + p.mpeg = 2; +// SCR = 0 + p.scr[0] = 0x44; + p.scr[1] = 0x00; + p.scr[2] = 0x04; + p.scr[3] = 0x00; + p.scr[4] = 0x04; + p.scr[5] = 0x01; + +// SCR = PTS + p.scr[0] = 0x44 | ((pts[0] >> 3)&0x18) | ((pts[0] >> 4)&0x03); + p.scr[1] = 0x00 | ((pts[0] << 4)&0xF0) | ((pts[1] >> 4)&0x0F); + p.scr[2] = 0x04 | ((pts[1] << 4)&0xF0) | ((pts[2] >> 4)&0x08) + | ((pts[2] >> 5)&0x03); + p.scr[3] = 0x00 | ((pts[2] << 3)&0xF8) | ((pts[3] >> 5)&0x07); + p.scr[4] = 0x04 | ((pts[3] << 3)&0xF8); + p.scr[5] = 0x01; + + p.mux_rate[0] = (uint8_t)(muxr >> 14); + p.mux_rate[1] = (uint8_t)(0xff & (muxr >> 6)); + p.mux_rate[2] = (uint8_t)(0x03 | ((muxr & 0x3f) << 2)); + + p.stuff_length = 0xF8; + + if (stream1 && stream2){ + p.sheader_llength[0] = 0x00; + p.sheader_llength[1] = 0x0c; + + setl_ps(&p); + + p.rate_bound[0] = (uint8_t)(0x80 | (muxr >>15)); + p.rate_bound[1] = (uint8_t)(0xff & (muxr >> 7)); + p.rate_bound[2] = (uint8_t)(0x01 | ((muxr & 0x7f)<<1)); + + + p.audio_bound = (uint8_t)((audio_bound << 2)|(fixed << 1)|CSPS); + p.video_bound = (uint8_t)((audio_lock << 7)| + (video_lock << 6)|0x20|video_bound); + p.reserved = (uint8_t)(0xFF >> 1); + + p.data[0] = stream2; + p.data[1] = (uint8_t) (0xc0 | (buffer2_scale << 5) | + (buffer2_size >> 8)); + p.data[2] = (uint8_t) (buffer2_size & 0xff); + p.data[3] = stream1; + p.data[4] = (uint8_t) (0xc0 | (buffer1_scale << 5) | + (buffer1_size >> 8)); + p.data[5] = (uint8_t) (buffer1_size & 0xff); + + cwrite_ps(buf, &p, PS_HEADER_L2); + kill_ps(&p); + return PS_HEADER_L2; + } else { + cwrite_ps(buf, &p, PS_HEADER_L1); + kill_ps(&p); + return PS_HEADER_L1; + } +} + + + +#define MAX_BASE 80 +#define MAX_PATH 256 +#define MAX_EXT 10 + +int break_up_filename(char *name, char *base_name, char *path, char *ext) +{ + int l,i,sstop,sstart; + + l = strlen(name); + sstop = l; + sstart = -1; + for( i= l-1; i >= 0; i--){ + if (sstop == l && name[i] == '.') sstop = i; + if (sstart<0 && name[i] == '/') sstart = i+1; + } + if (sstart < 0) sstart = 0; + if (sstop-sstart < MAX_BASE){ + strncpy(base_name, name+sstart, sstop-sstart); + base_name[sstop-sstart]=0; + if(sstart > 0){ + if( l - sstop + sstart < MAX_PATH){ + strncpy(path, name, sstart); + path[sstart] = 0; + } else { + fprintf(stderr,"PATH too long\n"); + return -1; + } + + } else { + strcpy(path, "./"); + } + + if(sstop < l){ + if( l - sstop -1 < MAX_EXT){ + strncpy(ext, name+sstop+1, l-sstop-1); + ext[l-sstop-1]=0; + } else { + fprintf(stderr,"Extension too long\n"); + return -1; + } + + } else { + strcpy(ext, ""); + } + + } else { + fprintf(stderr,"Name too long\n"); + return -1; + } +/* + printf("%d %d\n",sstart, sstop); + printf("%s %d\n",name, strlen(name)); + printf("%s %d\n",base_name, strlen(base_name)); + printf("%s %d\n",path,strlen(path)); + printf("%s %d\n",ext,strlen(ext)); +*/ + return 0; +} + + +int seek_mpg_start(uint8_t *buf, int size) +{ + int found = 0; + int c=0; + int seq = 0; + int mpeg = 0; + int mark = 0; + + while ( !seq ){ + while (found != 4){ + switch (found) { + case 0: + if ( buf[c] == 0x00 ) found++; + c++; + break; + case 1: + if ( buf[c] == 0x00 ) found++; + else found = 0; + c++; + break; + case 2: + if ( buf[c] == 0x01 ) found++; + else found = 0; + if ( buf[c] == 0x00 ) found = 2; + c++; + break; + + case 3: + if ( (buf[c] & 0xe0) == 0xe0 ) found++; + else found = 0; + c++; + break; + } + if (c >= size) return -1; + } + + if (found == 4){ + mark = c-4; + c+=2; + if (c >= size) return -1; + + if ( (buf[c] & 0xC0) == 0x80 ){ + mpeg = 2; + c += 2; + if (c >= size) return -1; + c += buf[c]+1; + if (c >= size) return -1; + } else { + mpeg = 1; + while( buf[c] == 0xFF ) { + c++; + if (c >= size) return -1; + } + if ( (buf[c] & 0xC0) == 0x40) c+=2; + if (c >= size) return -1; + if ( (buf[c] & 0x30) ){ + if ( (buf[c] & 0x30) == 0x20) c+=5; + else c+=10; + } else c++; + if (c >= size) return -1; + } + + if ( buf[c] == 0x00 && + buf[c+1] == 0x00 && + buf[c+2] == 0x01 && + buf[c+3] == 0xB3 ) + seq = 1; + } + found = 0; + } + + return size-mark; +} + + +void write_mpg(int fstart, uint64_t length, int fdin, int fdout) +{ +// uint8_t mpeg_end[4] = { 0x00, 0x00, 0x01, 0xB9 }; + uint8_t *buf; + uint64_t l=0; + uint64_t count = 0; + struct stat sb; + int buf_size; + + fstat (fdout, &sb); + buf_size = sb.st_blksize; + + buf = (uint8_t *) alloca (buf_size + sizeof (int)); + + lseek(fdin, fstart, SEEK_SET); + + while ( count < length && (l = read(fdin,buf,buf_size)) >= 0){ + if (l > 0) count+=l; + write(fdout,buf,l); + printf("written %02.2f%%\r",(100.*count)/length); + } + printf("\n"); + + //write( fdout, mpeg_end, 4); +} + + +#define CHECKBUF (1024*1024) +#define ONE_GIG (1024UL*1024UL*1024UL) +void split_mpg(char *name, uint64_t size) +{ + char base_name[MAX_BASE]; + char path[MAX_PATH]; + char ext[MAX_EXT]; + char new_name[256]; + uint8_t buf[CHECKBUF]; + int fdin; + int fdout; + uint64_t length = 0; + uint64_t last; + int i; + int mark, csize; + struct stat sb; + + if (break_up_filename(name,base_name,path,ext) < 0) exit(1); + + +#ifdef __FreeBSD__ + if ( (fdin = open(name, O_RDONLY)) < 0){ +#else + if ( (fdin = open(name, O_RDONLY|O_LARGEFILE)) < 0){ +#endif + fprintf(stderr,"Can't open %s\n",name); + exit(1); + } + + fstat (fdin, &sb); + + length = sb.st_size; + if ( length < ONE_GIG ) + printf("Filelength = %2.2f MB\n", length/1024./1024.); + else + printf("Filelength = %2.2f GB\n", length/1024./1024./1024.); + + if ( length < size ) length = size; + + printf("Splitting %s into Files with size <= %2.2f MB\n",name, + size/1024./1024.); + + csize = CHECKBUF; + read(fdin, buf, csize); + if ( (mark = seek_mpg_start(buf,csize)) < 0){ + fprintf(stderr,"Couldn't find sequence header\n"); + exit(1); + } + + last = csize-mark; + + for ( i = 0 ; i < length/size; i++){ + csize = CHECKBUF; + + if (csize > length-last) csize = length-last; + lseek(fdin, last+size-csize, SEEK_SET); + read(fdin, buf, csize); + if ( (mark = seek_mpg_start(buf,csize)) < 0){ + fprintf(stderr,"Couldn't find sequence header\n"); + exit(1); + } + + sprintf(new_name,"%s-%03d.%s",base_name,i,ext); + printf("writing %s\n",new_name); + +#ifdef __FreeBSD__ + if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC, +#else + if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC + |O_LARGEFILE, +#endif + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| + S_IROTH|S_IWOTH)) < 0){ + fprintf(stderr,"Can't open %s\n",new_name); + exit(1); + } + write_mpg(last, size-mark, fdin, fdout); + last = last + size - mark; + } + sprintf(new_name,"%s-%03d.%s",base_name,i,ext); + printf("writing %s\n",new_name); + +#ifdef __FreeBSD__ + if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC, +#else + if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC + |O_LARGEFILE, +#endif + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| + S_IROTH|S_IWOTH)) < 0){ + fprintf(stderr,"Can't open %s\n",new_name); + exit(1); + } + write_mpg(last, length-last, fdin, fdout); +} + + + + +void cut_mpg(char *name, uint64_t size) +{ + char base_name[MAX_BASE]; + char path[MAX_PATH]; + char ext[MAX_EXT]; + char new_name[256]; + uint8_t buf[CHECKBUF]; + int fdin; + int fdout; + uint64_t length = 0; + uint64_t last; + int mark, csize; + struct stat sb; + + if (break_up_filename(name,base_name,path,ext) < 0) exit(1); + + +#ifdef __FreeBSD__ + if ( (fdin = open(name, O_RDONLY)) < 0){ +#else + if ( (fdin = open(name, O_RDONLY|O_LARGEFILE)) < 0){ +#endif + fprintf(stderr,"Can't open %s\n",name); + exit(1); + } + + fstat (fdin, &sb); + + length = sb.st_size; + if ( length < ONE_GIG ) + printf("Filelength = %2.2f MB\n", length/1024./1024.); + else + printf("Filelength = %2.2f GB\n", length/1024./1024./1024.); + + if ( length < size ) length = size; + + printf("Splitting %s into 2 Files with length %.2f MB and %.2f MB\n", + name, size/1024./1024., (length-size)/1024./1024.); + + csize = CHECKBUF; + read(fdin, buf, csize); + if ( (mark = seek_mpg_start(buf,csize)) < 0){ + fprintf(stderr,"Couldn't find sequence header\n"); + exit(1); + } + + last = csize-mark; + + if (csize > length-last) csize = length-last; + lseek(fdin, last+size-csize, SEEK_SET); + read(fdin, buf, csize); + if ( (mark = seek_mpg_start(buf,csize)) < 0){ + fprintf(stderr,"Couldn't find sequence header\n"); + exit(1); + } + + sprintf(new_name,"%s-1.%s",base_name,ext); + printf("writing %s\n",new_name); + +#ifdef __FreeBSD__ + if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC, +#else + if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC + |O_LARGEFILE, +#endif + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| + S_IROTH|S_IWOTH)) < 0){ + fprintf(stderr,"Can't open %s\n",new_name); + exit(1); + } + write_mpg(last, size-mark, fdin, fdout); + last = last + size - mark; + + sprintf(new_name,"%s-2.%s",base_name,ext); + printf("writing %s\n",new_name); + +#ifdef __FreeBSD__ + if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC, +#else + if ( (fdout = open(new_name,O_WRONLY|O_CREAT|O_TRUNC + |O_LARGEFILE, +#endif + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| + S_IROTH|S_IWOTH)) < 0){ + fprintf(stderr,"Can't open %s\n",new_name); + exit(1); + } + write_mpg(last, length-last, fdin, fdout); +} + + + + +void write_all (int fd, const char *data, int length) +{ + int r; + + while (length) { + if ((r = write(fd, data, length)) > 0) { + data += r; + length -= r; + } + } +} + + + +void read_all (int fd, char *data, int length) +{ + int c = 0; + + while(1) { + if( read(fd, data+c, 1) == 1) { + c++; + if(data[c-1] == '\n') { + data[c] = 0; + break; + } + } + else { + fprintf (stderr, "Error reading socket\n"); + exit(1); + } + } +} + + + +char *url2host (char *url, char **name, uint32_t *ip, uint32_t *port) +{ + char *murl; + struct hostent *hoste; + struct in_addr haddr; + int found_ip = 1; + + if (!(strncmp(url, "http://", 7))) + url += 7; + + *name = strdup(url); + if (!(*name)) { + *name = NULL; + return (NULL); + } + + murl = url; + while (*murl && *murl != ':' && *murl != '/') { + if ((*murl < '0' || *murl > '9') && *murl != '.') + found_ip = 0; + murl++; + } + + (*name)[murl - url] = 0; + if (found_ip) { + if ((*ip = inet_addr(*name)) == INADDR_NONE) + return (NULL); + } else { + if (!(hoste = gethostbyname(*name))) + return (NULL); + memcpy (&haddr, hoste->h_addr, sizeof(haddr)); + *ip = haddr.s_addr; + } + + if (!*murl || *murl == '/') { + *port = 80; + return (murl); + } + *port = atoi(++murl); + + while (*murl && *murl != '/') + murl++; + return (murl); +} + +#define ACCEPT "Accept: video/mpeg, video/x-mpegurl, */*\r\n" + +int http_open (char *url) +{ + char purl[1024], *host, req[1024], *sptr; + uint32_t ip; + uint32_t port; + int sock; + int reloc, relocnum = 0; + struct sockaddr_in server; + int mfd; + + strncpy (purl, url, 1023); + purl[1023] = '\0'; + + do { + host = NULL; + strcpy (req, "GET "); + if (!(sptr = url2host(purl, &host, &ip, &port))) { + fprintf (stderr, "Unknown host\n"); + exit (1); + } + strcat (req, sptr); + sprintf (req + strlen(req), + " HTTP/1.0\r\nUser-Agent: %s/%s\r\n", + "whatever", "you want"); + if (host) { + sprintf(req + strlen(req), + "Host: %s:%u\r\n", host, port); + free (host); + } + + strcat (req, ACCEPT); + strcat (req, "\r\n"); + + server.sin_port = htons(port); + server.sin_family = AF_INET; + server.sin_addr.s_addr = ip; + + if ((sock = socket(PF_INET, SOCK_STREAM, 6)) < 0) { + perror ("socket"); + exit (1); + } + + if (connect(sock, (struct sockaddr *)&server, + sizeof(server))) { + perror ("connect"); + exit (1); + } + + write_all (sock, req, strlen(req)); + if (!(mfd = fileno(fdopen(sock, "rb")))) { + perror ("open"); + exit (1); + } + reloc = 0; + purl[0] = '\0'; + read_all (mfd, req, 1023); + if ((sptr = strchr(req, ' '))) { + switch (sptr[1]) { + case '2': + break; + case '3': + reloc = 1; + default: + fprintf (stderr, "HTTP req failed:%s", + sptr+1); + exit (1); + } + } + do { + read_all (mfd,req, 1023); + if (!strncmp(req, "Location:", 9)) + strncpy (purl, req+10, 1023); + } while (req[0] != '\r' && req[0] != '\n'); + } while (reloc && purl[0] && relocnum++ < 3); + if (reloc) { + fprintf (stderr, "Too many HTTP relocations.\n"); + exit (1); + } + + return sock; +} + +extern int errno; +const char * strerrno (void) +{ + return strerror(errno); +} diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/ctools.h b/plugins/streamdev/streamdev-cvs/libdvbmpeg/ctools.h new file mode 100644 index 0000000..a7b0271 --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/ctools.h @@ -0,0 +1,404 @@ +/* + * dvb-mpegtools for the Siemens Fujitsu DVB PCI card + * + * Copyright (C) 2000, 2001 Marcus Metzler + * for convergence integrated media GmbH + * Copyright (C) 2002, 2003 Marcus Metzler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + + * The author can be reached at mocm@metzlerbros.de + + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "ringbuffy.h" +#include "transform.h" + +#ifndef _CTOOLS_H_ +#define _CTOOLS_H_ + +#define VIDEO_MODE_PAL 0 +#define VIDEO_MODE_NTSC 1 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + enum {PS_STREAM, TS_STREAM, PES_STREAM}; + enum {pDUNNO, pPAL, pNTSC}; + + uint64_t trans_pts_dts(uint8_t *pts); + +/* + PES +*/ + +#define PROG_STREAM_MAP 0xBC +#ifndef PRIVATE_STREAM1 +#define PRIVATE_STREAM1 0xBD +#endif +#define PADDING_STREAM 0xBE +#ifndef PRIVATE_STREAM2 +#define PRIVATE_STREAM2 0xBF +#endif +#define AUDIO_STREAM_S 0xC0 +#define AUDIO_STREAM_E 0xDF +#define VIDEO_STREAM_S 0xE0 +#define VIDEO_STREAM_E 0xEF +#define ECM_STREAM 0xF0 +#define EMM_STREAM 0xF1 +#define DSM_CC_STREAM 0xF2 +#define ISO13522_STREAM 0xF3 +#define PROG_STREAM_DIR 0xFF + +#define BUFFYSIZE 10*MAX_PLENGTH +#define MAX_PTS 8192 +#define MAX_FRAME 8192 +#define MAX_PACK_L 4096 +#define PS_HEADER_L1 14 +#define PS_HEADER_L2 (PS_HEADER_L1+18) +#define MAX_H_SIZE (PES_H_MIN + PS_HEADER_L1 + 5) +#define PES_MIN 7 +#define PES_H_MIN 9 + +//flags1 +#define FLAGS 0x40 +#define SCRAMBLE_FLAGS 0x30 +#define PRIORITY_FLAG 0x08 +#define DATA_ALIGN_FLAG 0x04 +#define COPYRIGHT_FLAG 0x02 +#define ORIGINAL_FLAG 0x01 + +//flags2 +#define PTS_DTS_FLAGS 0xC0 +#define ESCR_FLAG 0x20 +#define ES_RATE_FLAG 0x10 +#define DSM_TRICK_FLAG 0x08 +#define ADD_CPY_FLAG 0x04 +#define PES_CRC_FLAG 0x02 +#define PES_EXT_FLAG 0x01 + +//pts_dts flags +#define PTS_ONLY 0x80 +#define PTS_DTS 0xC0 + +//private flags +#define PRIVATE_DATA 0x80 +#define HEADER_FIELD 0x40 +#define PACK_SEQ_CTR 0x20 +#define P_STD_BUFFER 0x10 +#define PES_EXT_FLAG2 0x01 + +#define MPEG1_2_ID 0x40 +#define STFF_LNGTH_MASK 0x3F + + + typedef struct pes_packet_{ + uint8_t stream_id; + uint8_t llength[2]; + uint32_t length; + uint8_t flags1; + uint8_t flags2; + uint8_t pes_hlength; + uint8_t pts[5]; + uint8_t dts[5]; + uint8_t escr[6]; + uint8_t es_rate[3]; + uint8_t trick; + uint8_t add_cpy; + uint8_t prev_pes_crc[2]; + uint8_t priv_flags; + uint8_t pes_priv_data[16]; + uint8_t pack_field_length; + uint8_t *pack_header; + uint8_t pck_sqnc_cntr; + uint8_t org_stuff_length; + uint8_t p_std[2]; + uint8_t pes_ext_lngth; + uint8_t *pes_ext; + uint8_t *pes_pckt_data; + int padding; + int mpeg; + int mpeg1_pad; + uint8_t *mpeg1_headr; + uint8_t stuffing; + } pes_packet; + + void init_pes(pes_packet *p); + void kill_pes(pes_packet *p); + void setlength_pes(pes_packet *p); + void nlength_pes(pes_packet *p); + int cwrite_pes(uint8_t *buf, pes_packet *p, long length); + void write_pes(int fd, pes_packet *p); + int read_pes(int f, pes_packet *p); + void cread_pes(char *buf, pes_packet *p); + +/* + Transport Stream +*/ + +#define TS_SIZE 188 +#define TRANS_ERROR 0x80 +#define PAY_START 0x40 +#define TRANS_PRIO 0x20 +#define PID_MASK_HI 0x1F +//flags +#define TRANS_SCRMBL1 0x80 +#define TRANS_SCRMBL2 0x40 +#define ADAPT_FIELD 0x20 +#define PAYLOAD 0x10 +#define COUNT_MASK 0x0F + +// adaptation flags +#define DISCON_IND 0x80 +#define RAND_ACC_IND 0x40 +#define ES_PRI_IND 0x20 +#define PCR_FLAG 0x10 +#define OPCR_FLAG 0x08 +#define SPLICE_FLAG 0x04 +#define TRANS_PRIV 0x02 +#define ADAP_EXT_FLAG 0x01 + +// adaptation extension flags +#define LTW_FLAG 0x80 +#define PIECE_RATE 0x40 +#define SEAM_SPLICE 0x20 + + typedef struct ts_packet_{ + uint8_t pid[2]; + uint8_t flags; + uint8_t count; + uint8_t data[184]; + uint8_t adapt_length; + uint8_t adapt_flags; + uint8_t pcr[6]; + uint8_t opcr[6]; + uint8_t splice_count; + uint8_t priv_dat_len; + uint8_t *priv_dat; + uint8_t adapt_ext_len; + uint8_t adapt_eflags; + uint8_t ltw[2]; + uint8_t piece_rate[3]; + uint8_t dts[5]; + int rest; + uint8_t stuffing; + } ts_packet; + + void init_ts(ts_packet *p); + void kill_ts(ts_packet *p); + unsigned short pid_ts(ts_packet *p); + int cwrite_ts(uint8_t *buf, ts_packet *p, long length); + void write_ts(int fd, ts_packet *p); + int read_ts(int f, ts_packet *p); + void cread_ts (char *buf, ts_packet *p, long length); + + +/* + Program Stream +*/ + +#define PACK_STUFF_MASK 0x07 + +#define FIXED_FLAG 0x02 +#define CSPS_FLAG 0x01 +#define SAUDIO_LOCK_FLAG 0x80 +#define SVIDEO_LOCK_FLAG 0x40 + +#define PS_MAX 200 + + typedef struct ps_packet_{ + uint8_t scr[6]; + uint8_t mux_rate[3]; + uint8_t stuff_length; + uint8_t *data; + uint8_t sheader_llength[2]; + int sheader_length; + uint8_t rate_bound[3]; + uint8_t audio_bound; + uint8_t video_bound; + uint8_t reserved; + int npes; + int mpeg; + } ps_packet; + + void init_ps(ps_packet *p); + void kill_ps(ps_packet *p); + void setlength_ps(ps_packet *p); + uint32_t scr_base_ps(ps_packet *p); + uint16_t scr_ext_ps(ps_packet *p); + int mux_ps(ps_packet *p); + int rate_ps(ps_packet *p); + int cwrite_ps(uint8_t *buf, ps_packet *p, long length); + void write_ps(int fd, ps_packet *p); + int read_ps (int f, ps_packet *p); + void cread_ps (char *buf, ps_packet *p, long length); + + + +#define MAX_PLENGTH 0xFFFF + + typedef struct sectionstruct { + int id; + int length; + int found; + uint8_t payload[4096+3]; + } section; + + + typedef uint32_t tflags; +#define MAXFILT 32 +#define MASKL 16 + typedef struct trans_struct { + int found; + uint8_t packet[188]; + uint16_t pid[MAXFILT]; + uint8_t mask[MAXFILT*MASKL]; + uint8_t filt[MAXFILT*MASKL]; + uint8_t transbuf[MAXFILT*188]; + int transcount[MAXFILT]; + section sec[MAXFILT]; + tflags is_full; + tflags pes_start; + tflags pes_started; + tflags pes; + tflags set; + } trans; + + + void init_trans(trans *p); + int set_trans_filt(trans *p, int filtn, uint16_t pid, uint8_t *mask, + uint8_t *filt, int pes); + + void clear_trans_filt(trans *p,int filtn); + int filt_is_set(trans *p, int filtn); + int pes_is_set(trans *p, int filtn); + int pes_is_started(trans *p, int filtn); + int pes_is_start(trans *p, int filtn); + int filt_is_ready(trans *p,int filtn); + + void trans_filt(uint8_t *buf, int count, trans *p); + void tfilter(trans *p); + void pes_filter(trans *p, int filtn, int off); + void sec_filter(trans *p, int filtn, int off); + int get_filt_buf(trans *p, int filtn,uint8_t **buf); + section *get_filt_sec(trans *p, int filtn); + + + typedef struct a2pstruct{ + int type; + int fd; + int found; + int length; + int headr; + int plength; + uint8_t cid; + uint8_t flags; + uint8_t abuf[MAX_PLENGTH]; + int alength; + uint8_t vbuf[MAX_PLENGTH]; + int vlength; + uint8_t last_av_pts[4]; + uint8_t av_pts[4]; + uint8_t scr[4]; + uint8_t pid0; + uint8_t pid1; + uint8_t pidv; + uint8_t pida; + } a2p; + + + + void get_pespts(uint8_t *av_pts,uint8_t *pts); + void init_a2p(a2p *p); + void av_pes_to_pes(uint8_t *buf,int count, a2p *p); + int w_pesh(uint8_t id,int length ,uint8_t *pts, uint8_t *obuf); + int w_tsh(uint8_t id,int length ,uint8_t *pts, uint8_t *obuf,a2p *p,int startpes); + void pts2pts(uint8_t *av_pts, uint8_t *pts); + void write_ps_headr(ps_packet *p,uint8_t *pts,int fd); + + typedef struct p2t_s{ + uint8_t pes[TS_SIZE]; + uint8_t counter; + long int pos; + int frags; + void (*t_out)(uint8_t const *buf); + } p2t_t; + + void twrite(uint8_t const *buf); + void init_p2t(p2t_t *p, void (*fkt)(uint8_t const *buf)); + long int find_pes_header(uint8_t const *buf, long int length, int *frags); + void pes_to_ts( uint8_t const *buf, long int length, uint16_t pid, p2t_t *p); + void p_to_t( uint8_t const *buf, long int length, uint16_t pid, + uint8_t *counter, void (*ts_write)(uint8_t const *)); + + + int write_pes_header(uint8_t id,int length , long PTS, + uint8_t *obuf, int stuffing); + + int write_ps_header(uint8_t *buf, + uint32_t SCR, + long muxr, + uint8_t audio_bound, + uint8_t fixed, + uint8_t CSPS, + uint8_t audio_lock, + uint8_t video_lock, + uint8_t video_bound, + uint8_t stream1, + uint8_t buffer1_scale, + uint32_t buffer1_size, + uint8_t stream2, + uint8_t buffer2_scale, + uint32_t buffer2_size); + + + int seek_mpg_start(uint8_t *buf, int size); + + + void split_mpg(char *name, uint64_t size); + void cut_mpg(char *name, uint64_t size); + int http_open (char *url); + ssize_t save_read(int fd, void *buf, size_t count); + + const char * strerrno(void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*_CTOOLS_H_*/ diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/remux.c b/plugins/streamdev/streamdev-cvs/libdvbmpeg/remux.c new file mode 100644 index 0000000..1d65525 --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/remux.c @@ -0,0 +1,1215 @@ +/* + * dvb-mpegtools for the Siemens Fujitsu DVB PCI card + * + * Copyright (C) 2000, 2001 Marcus Metzler + * for convergence integrated media GmbH + * Copyright (C) 2002 Marcus Metzler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + + * The author can be reached at mocm@metzlerbros.de, + */ + +#include "remux.h" + +unsigned int bitrates[3][16] = +{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, + {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, + {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}}; + +uint32_t freq[4] = {441, 480, 320, 0}; +static uint32_t samples[4] = { 384, 1152, 0, 0}; +char *frames[3] = {"I-Frame","P-Frame","B-Frame"}; + + +void copy_ptslm(PTS_List *a, PTS_List *b) +{ + a->pos = b->pos; + a->PTS = b->PTS; + a->dts = b->dts; + a->spos = b->spos; +} + +void clear_ptslm(PTS_List *a) +{ + a->pos = 0; + a->PTS = 0; + a->dts = 0; + a->spos = 0; +} + +void init_ptsl(PTS_List *ptsl) +{ + int i; + for (i=0;i< MAX_PTS;i++){ + clear_ptslm(&ptsl[i]); + } +} + +int del_pts(PTS_List *ptsl, int pos, int nr) +{ + int i; + int del = 0; + + for( i = 0; i < nr-1; i++){ + if(pos > ptsl[i].pos && pos >= ptsl[i+1].pos) del++; + } + + if(del) + for( i = 0; i < nr-del; i++){ + copy_ptslm(&ptsl[i], &ptsl[i+del]); + } + + return nr-del; +} + +int del_ptss(PTS_List *ptsl, int pts, int *nb) +{ + int i; + int del = 0; + int sum = 0; + int nr = *nb; + + for( i = 0; i < nr; i++){ + if(pts > ptsl[i].PTS){ + del++; + sum += ptsl[i].pos; + } + } + + if(del) + for( i = 0; i < nr-del; i++){ + copy_ptslm(&ptsl[i], &ptsl[i+del]); + } + + *nb = nr-del; + return sum; +} + +int add_pts(PTS_List *ptsl, uint32_t pts, int pos, int spos, int nr, uint32_t dts) +{ + int i; + + for ( i=0;i < nr; i++) if (spos && ptsl[i].pos == pos) return nr; + if (nr == MAX_PTS) { + nr = del_pts(ptsl, ptsl[1].pos+1, nr); + } else nr++; + i = nr-1; + + ptsl[i].pos = pos; + ptsl[i].spos = spos; + ptsl[i].PTS = pts; + ptsl[i].dts = dts; + return nr; +} + +void add_vpts(Remux *rem, uint8_t *pts) +{ + uint32_t PTS = trans_pts_dts(pts); + rem->vptsn = add_pts(rem->vpts_list, PTS, rem->vwrite, rem->awrite, + rem->vptsn, PTS); +} + +void add_apts(Remux *rem, uint8_t *pts) +{ + uint32_t PTS = trans_pts_dts(pts); + rem->aptsn = add_pts(rem->apts_list, PTS, rem->awrite, rem->vwrite, + rem->aptsn, PTS); +} + +void del_vpts(Remux *rem) +{ + rem->vptsn = del_pts(rem->vpts_list, rem->vread, rem->vptsn); +} + +void del_apts(Remux *rem) +{ + rem->aptsn = del_pts(rem->apts_list, rem->aread, rem->aptsn); +} + + +void copy_framelm(FRAME_List *a, FRAME_List *b) +{ + a->type = b->type; + a->pos = b->pos; + a->FRAME = b->FRAME; + a->time = b->time; + a->pts = b->pts; + a->dts = b->dts; +} + +void clear_framelm(FRAME_List *a) +{ + a->type = 0; + a->pos = 0; + a->FRAME = 0; + a->time = 0; + a->pts = 0; + a->dts = 0; +} + +void init_framel(FRAME_List *framel) +{ + int i; + for (i=0;i< MAX_FRAME;i++){ + clear_framelm(&framel[i]); + } +} + +int del_frame(FRAME_List *framel, int pos, int nr) +{ + int i; + int del = 0; + + for( i = 0; i < nr-1; i++){ + if(pos > framel[i].pos && pos >= framel[i+1].pos) del++; + } + + if(del) + for( i = 0; i < nr-del; i++){ + copy_framelm(&framel[i], &framel[i+del]); + } + + return nr-del; +} + +int add_frame(FRAME_List *framel, uint32_t frame, int pos, int type, int nr, + uint32_t time, uint32_t pts, uint32_t dts) +{ + int i; + + if (nr == MAX_FRAME) { + nr = del_frame(framel, framel[1].pos+1, nr); + } else nr++; + i = nr-1; + + framel[i].type = type; + framel[i].pos = pos; + framel[i].FRAME = frame; + framel[i].time = time; + framel[i].pts = pts; + framel[i].dts = dts; + return nr; +} + +void add_vframe(Remux *rem, uint32_t frame, long int pos, int type, int time, + uint32_t pts, uint32_t dts) +{ + rem->vframen = add_frame(rem->vframe_list, frame, pos, type, + rem->vframen, time, pts, dts); +} + +void add_aframe(Remux *rem, uint32_t frame, long int pos, uint32_t pts) +{ + rem->aframen = add_frame(rem->aframe_list, frame, pos, 0, + rem->aframen, 0, pts, pts); +} + +void del_vframe(Remux *rem) +{ + rem->vframen = del_frame(rem->vframe_list, rem->vread, rem->vframen); +} + +void del_aframe(Remux *rem) +{ + rem->aframen = del_frame(rem->aframe_list, rem->aread, rem->aframen); +} + + +void printpts(uint32_t pts) +{ + fprintf(stderr,"%2d:%02d:%02d.%03d", + (int)(pts/90000.)/3600, + ((int)(pts/90000.)%3600)/60, + ((int)(pts/90000.)%3600)%60, + (((int)(pts/90.)%3600000)%60000)%1000 + ); +} + + +void find_vframes( Remux *rem, uint8_t *buf, int l) +{ + int c = 0; + int type; + uint32_t time = 0; + int hour; + int min; + int sec; + uint64_t pts=0; + uint64_t dts=0; + uint32_t tempref = 0; + + while ( c < l - 6){ + if (buf[c] == 0x00 && + buf[c+1] == 0x00 && + buf[c+2] == 0x01 && + buf[c+3] == 0xB8) { + c += 4; + hour = (int)((buf[c]>>2)& 0x1F); + min = (int)(((buf[c]<<4)& 0x30)| + ((buf[c+1]>>4)& 0x0F)); + sec = (int)(((buf[c+1]<<3)& 0x38)| + ((buf[c+2]>>5)& 0x07)); + + time = 3600*hour + 60*min + sec; + if ( rem->time_off){ + time = (uint32_t)((uint64_t)time - rem->time_off); + hour = time/3600; + min = (time%3600)/60; + sec = (time%3600)%60; + /* + buf[c] |= (hour & 0x1F) << 2; + buf[c] |= (min & 0x30) >> 4; + buf[c+1] |= (min & 0x0F) << 4; + buf[c+1] |= (sec & 0x38) >> 3; + buf[c+2] |= (sec & 0x07) >> 5;*/ + } + rem->group++; + rem->groupframe = 0; + } + if ( buf[c] == 0x00 && + buf[c+1] == 0x00 && + buf[c+2] == 0x01 && + buf[c+3] == 0x00) { + c += 4; + tempref = (buf[c+1]>>6) & 0x03; + tempref |= buf[c] << 2; + + type = ((buf[c+1]&0x38) >>3); + if ( rem->video_info.framerate){ + pts = ((uint64_t)rem->vframe + tempref + 1 + - rem->groupframe ) * 90000ULL + /rem->video_info.framerate + + rem->vpts_off; + dts = (uint64_t)rem->vframe * 90000ULL/ + rem->video_info.framerate + + rem->vpts_off; + + +fprintf(stderr,"MYPTS:"); +printpts((uint32_t)pts-rem->vpts_off); + fprintf(stderr," REALPTS:"); + printpts(rem->vpts_list[rem->vptsn-1].PTS-rem->vpts_off); + fprintf(stderr," DIFF:"); + printpts(pts-(uint64_t)rem->vpts_list[rem->vptsn-1].PTS); +// fprintf(stderr," DIST: %4d",-rem->vpts_list[rem->vptsn-1].pos+(rem->vwrite+c-4)); + //fprintf(stderr," ERR: %3f",(double)(-rem->vpts_list[rem->vptsn-1].PTS+pts)/(rem->vframe+1)); + fprintf(stderr,"\r"); + + + + rem->vptsn = add_pts(rem->vpts_list,(uint32_t)pts + ,rem->vwrite+c-4, + rem->awrite, + rem->vptsn, + (uint32_t)dts); + + + + } + rem->vframe++; + rem->groupframe++; + add_vframe( rem, rem->vframe, rem->vwrite+c, type, + time, pts, dts); + } else c++; + } +} + +void find_aframes( Remux *rem, uint8_t *buf, int l) +{ + int c = 0; + uint64_t pts = 0; + int sam; + uint32_t fr; + + + while ( c < l - 2){ + if ( buf[c] == 0xFF && + (buf[c+1] & 0xF8) == 0xF8) { + c += 2; + if ( rem->audio_info.layer >= 0){ + sam = samples[3-rem->audio_info.layer]; + fr = freq[rem->audio_info.frequency] ; + + pts = ( (uint64_t)rem->aframe * sam * 900ULL)/fr + + rem->apts_off; + + +fprintf(stderr,"MYPTS:"); +printpts((uint32_t)pts-rem->apts_off); + fprintf(stderr," REALPTS:"); + printpts(rem->apts_list[rem->aptsn-1].PTS-rem->apts_off); + fprintf(stderr," DIFF:"); + printpts((uint32_t)((uint64_t)rem->apts_list[rem->aptsn-1].PTS-pts)); +// fprintf(stderr," DIST: %4d",-rem->apts_list[rem->aptsn-1].pos+(rem->awrite+c-2)); + fprintf(stderr,"\r"); + + rem->aptsn = add_pts(rem->apts_list,(uint32_t)pts + ,rem->awrite+c-2, + rem->vwrite, + rem->aptsn, + (uint32_t)pts); + } + + rem->aframe++; + add_aframe( rem, rem->aframe, rem->awrite+c, pts); + + } else c++; + } +} + +int refill_buffy(Remux *rem) +{ + pes_packet pes; + int count = 0; + int acount, vcount; + ringbuffy *vbuf = &rem->vid_buffy; + ringbuffy *abuf = &rem->aud_buffy; + int fin = rem->fin; + + acount = abuf->size-ring_rest(abuf); + vcount = vbuf->size-ring_rest(vbuf); + + + while ( acount > MAX_PLENGTH && vcount > MAX_PLENGTH && count < 10){ + int neof; + count++; + init_pes(&pes); + if ((neof = read_pes(fin,&pes)) <= 0) return -1; + switch(pes.stream_id){ + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + rem->apes++; + if( rem->audio_info.layer < 0 && + (pes.flags2 & PTS_DTS) ) + add_apts(rem, pes.pts); + find_aframes( rem, pes.pes_pckt_data, pes.length); + ring_write(abuf,(char *)pes.pes_pckt_data,pes.length); + rem->awrite += pes.length; + break; + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + rem->vpes++; + if( !rem->video_info.framerate && + (pes.flags2 & PTS_DTS) ) + add_vpts(rem, pes.pts); + + find_vframes( rem, pes.pes_pckt_data, pes.length); + + ring_write(vbuf,(char *)pes.pes_pckt_data,pes.length); + rem->vwrite += pes.length; + break; + } + acount = abuf->size-ring_rest(abuf); + vcount = vbuf->size-ring_rest(vbuf); + kill_pes(&pes); + } + if (count < 10) return 0; + return 1; +} + +int vring_read( Remux *rem, uint8_t *buf, int l) +{ + int c = 0; + int r = 0; + + if (ring_rest(&rem->vid_buffy) <= l) + r = refill_buffy(rem); + if (r) return -1; + + c = ring_read(&rem->vid_buffy, (char *) buf, l); + rem->vread += c; + del_vpts(rem); + del_vframe(rem); + return c; +} + +int aring_read( Remux *rem, uint8_t *buf, int l) +{ + int c = 0; + int r = 0; + + if (ring_rest(&rem->aud_buffy) <= l) + r = refill_buffy(rem); + if (r) return -1; + + c = ring_read(&rem->aud_buffy, (char *)buf, l); + rem->aread += c; + del_apts(rem); + del_aframe(rem); + return c; +} + +int vring_peek( Remux *rem, uint8_t *buf, int l, long off) +{ + int c = 0; + + if (ring_rest(&rem->vid_buffy) <= l) + refill_buffy(rem); + + c = ring_peek(&rem->vid_buffy, (char *) buf, l, off); + return c; +} + +int aring_peek( Remux *rem, uint8_t *buf, int l, long off) +{ + int c = 0; + + if (ring_rest(&rem->aud_buffy) <= l) + refill_buffy(rem); + + c = ring_peek(&rem->aud_buffy, (char *)buf, l, off); + return c; +} + + +int get_video_info(Remux *rem) +{ + uint8_t buf[12]; + uint8_t *headr; + int found = 0; + int sw; + long off = 0; + int form = -1; + ringbuffy *vid_buffy = &rem->vid_buffy; + VideoInfo *vi = &rem->video_info; + + while (found < 4 && ring_rest(vid_buffy)){ + uint8_t b[4]; + + vring_peek( rem, b, 4, 0); + if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01 + && b[3] == 0xb3) found = 4; + else { + off++; + vring_read( rem, b, 1); + } + } + rem->vframe = rem->vframen-1; + + if (! found) return -1; + buf[0] = 0x00; buf[1] = 0x00; buf[2] = 0x01; buf[3] = 0xb3; + headr = buf+4; + if(vring_peek(rem, buf, 12, 0) < 12) return -1; + + vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4); + vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]); + + sw = (int)((headr[3]&0xF0) >> 4) ; + + switch( sw ){ + case 1: + fprintf(stderr,"Videostream: ASPECT: 1:1"); + vi->aspect_ratio = 100; + break; + case 2: + fprintf(stderr,"Videostream: ASPECT: 4:3"); + vi->aspect_ratio = 133; + break; + case 3: + fprintf(stderr,"Videostream: ASPECT: 16:9"); + vi->aspect_ratio = 177; + break; + case 4: + fprintf(stderr,"Videostream: ASPECT: 2.21:1"); + vi->aspect_ratio = 221; + break; + + case 5 ... 15: + fprintf(stderr,"Videostream: ASPECT: reserved"); + vi->aspect_ratio = 0; + break; + + default: + vi->aspect_ratio = 0; + return -1; + } + + fprintf(stderr," Size = %dx%d",vi->horizontal_size,vi->vertical_size); + + sw = (int)(headr[3]&0x0F); + + switch ( sw ) { + case 1: + fprintf(stderr," FRate: 23.976 fps"); + vi->framerate = 24000/1001.; + form = -1; + break; + case 2: + fprintf(stderr," FRate: 24 fps"); + vi->framerate = 24; + form = -1; + break; + case 3: + fprintf(stderr," FRate: 25 fps"); + vi->framerate = 25; + form = VIDEO_MODE_PAL; + break; + case 4: + fprintf(stderr," FRate: 29.97 fps"); + vi->framerate = 30000/1001.; + form = VIDEO_MODE_NTSC; + break; + case 5: + fprintf(stderr," FRate: 30 fps"); + vi->framerate = 30; + form = VIDEO_MODE_NTSC; + break; + case 6: + fprintf(stderr," FRate: 50 fps"); + vi->framerate = 50; + form = VIDEO_MODE_PAL; + break; + case 7: + fprintf(stderr," FRate: 60 fps"); + vi->framerate = 60; + form = VIDEO_MODE_NTSC; + break; + } + + rem->dts_delay = (int)(7.0/vi->framerate/2.0*90000); + + vi->bit_rate = 400*(((headr[4] << 10) & 0x0003FC00UL) + | ((headr[5] << 2) & 0x000003FCUL) | + (((headr[6] & 0xC0) >> 6) & 0x00000003UL)); + + fprintf(stderr," BRate: %.2f Mbit/s",(vi->bit_rate)/1000000.); + + fprintf(stderr,"\n"); + vi->video_format = form; + + /* + marker_bit (&video_bs, 1); + vi->vbv_buffer_size = getbits (&video_bs, 10); + vi->CSPF = get1bit (&video_bs); + */ + return form; +} + + +int get_audio_info( Remux *rem) +{ + uint8_t *headr; + uint8_t buf[3]; + long off = 0; + int found = 0; + ringbuffy *aud_buffy = &rem->aud_buffy; + AudioInfo *ai = &rem->audio_info; + + while(!ring_rest(aud_buffy) && !refill_buffy(rem)); + while (found < 2 && ring_rest(aud_buffy)){ + uint8_t b[2]; + refill_buffy(rem); + aring_peek( rem, b, 2, 0); + + if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8) + found = 2; + else { + off++; + aring_read( rem, b, 1); + } + } + + if (!found) return -1; + rem->aframe = rem->aframen-1; + + if (aring_peek(rem, buf, 3, 0) < 1) return -1; + headr = buf+2; + + ai->layer = (buf[1] & 0x06) >> 1; + + fprintf(stderr,"Audiostream: Layer: %d", 4-ai->layer); + + + ai->bit_rate = bitrates[(3-ai->layer)][(headr[0] >> 4 )]*1000; + + if (ai->bit_rate == 0) + fprintf (stderr," Bit rate: free"); + else if (ai->bit_rate == 0xf) + fprintf (stderr," BRate: reserved"); + else + fprintf (stderr," BRate: %d kb/s", ai->bit_rate/1000); + + + ai->frequency = (headr[0] & 0x0c ) >> 2; + if (ai->frequency == 3) + fprintf (stderr, " Freq: reserved\n"); + else + fprintf (stderr," Freq: %2.1f kHz\n", + freq[ai->frequency]/10.); + + return 0; +} + + + +void init_remux(Remux *rem, int fin, int fout, int mult) +{ + rem->video_info.framerate = 0; + rem->audio_info.layer = -1; + rem->fin = fin; + rem->fout = fout; + ring_init(&rem->vid_buffy, 40*BUFFYSIZE*mult); + ring_init(&rem->aud_buffy, BUFFYSIZE*mult); + init_ptsl(rem->vpts_list); + init_ptsl(rem->apts_list); + init_framel(rem->vframe_list); + init_framel(rem->aframe_list); + + rem->vptsn = 0; + rem->aptsn = 0; + rem->vframen = 0; + rem->aframen = 0; + rem->vframe = 0; + rem->aframe = 0; + rem->vcframe = 0; + rem->acframe = 0; + rem->vpts = 0; + rem->vdts = 0; + rem->apts_off = 0; + rem->vpts_off = 0; + rem->apts_delay= 0; + rem->vpts_delay= 0; + rem->dts_delay = 0; + rem->apts = 0; + rem->vpes = 0; + rem->apes = 0; + rem->vpts_old = 0; + rem->apts_old = 0; + rem->SCR = 0; + rem->vwrite = 0; + rem->awrite = 0; + rem->vread = 0; + rem->aread = 0; + rem->group = 0; + rem->groupframe= 0; + rem->pack_size = 0; + rem->muxr = 0; + rem->time_off = 0; +} + +uint32_t bytes2pts(int bytes, int rate) +{ + if (bytes < 0xFFFFFFFFUL/720000UL) + return (uint32_t)(bytes*720000UL/rate); + else + return (uint32_t)(bytes/rate*720000UL); +} + +long pts2bytes( uint32_t pts, int rate) +{ + if (pts < 0xEFFFFFFFUL/rate) + return (pts*rate/720000); + else + return (pts* (rate/720000)); +} + +int write_audio_pes( Remux *rem, uint8_t *buf, int *alength) +{ + int add; + int pos = 0; + int p = 0; + uint32_t pts = 0; + int stuff = 0; + int length = *alength; + + if (!length) return 0; + p = PS_HEADER_L1+PES_H_MIN; + + if (rem->apts_old != rem->apts){ + pts = (uint32_t)((uint64_t)rem->apts + rem->apts_delay - rem->apts_off); + p += 5; + } + if ( length+p >= rem->pack_size){ + length = rem->pack_size; + } else { + if (rem->pack_size-length-p <= PES_MIN){ + stuff = rem->pack_size - length; + length = rem->pack_size; + } else + length = length+p; + } + pos = write_ps_header(buf,rem->SCR,rem->muxr, 1, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0); + + pos += write_pes_header( 0xC0, length-pos, pts, buf+pos, stuff); + add = aring_read( rem, buf+pos, length-pos); + *alength = add; + if (add < 0) return -1; + pos += add; + rem->apts_old = rem->apts; + rem->apts = rem->apts_list[0].PTS; + + if (pos+PES_MIN < rem->pack_size){ + pos += write_pes_header( PADDING_STREAM, rem->pack_size-pos, 0, + buf+pos, 0); + pos = rem->pack_size; + } + if (pos != rem->pack_size) { + fprintf(stderr,"apos: %d\n",pos); + exit(1); + } + + return pos; +} + +int write_video_pes( Remux *rem, uint8_t *buf, int *vlength) +{ + int add; + int pos = 0; + int p = 0; + uint32_t pts = 0; + uint32_t dts = 0; + int stuff = 0; + int length = *vlength; + long diff = 0; + + if (! length) return 0; + p = PS_HEADER_L1+PES_H_MIN; + + if (rem->vpts_old != rem->vpts){ + pts = (uint32_t)((uint64_t)rem->vpts + rem->vpts_delay - rem->vpts_off); + p += 5; + } + if ( length+p >= rem->pack_size){ + length = rem->pack_size; + } else { + if (rem->pack_size - length - p <= PES_MIN){ + stuff = rem->pack_size - length; + length = rem->pack_size; + } else + length = length+p; + } + + pos = write_ps_header(buf,rem->SCR,rem->muxr, 1, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0); + + pos += write_pes_header( 0xE0, length-pos, pts, buf+pos, stuff); + add = vring_read( rem, buf+pos, length-pos); + *vlength = add; + if (add < 0) return -1; + pos += add; + rem->vpts_old = rem->vpts; + dts = rem->vdts; + rem->vpts = rem->vpts_list[0].PTS; + rem->vdts = rem->vpts_list[0].dts; + if ( diff > 0) rem->SCR += diff; + if (pos+PES_MIN < rem->pack_size){ + // fprintf(stderr,"vstuffing: %d \n",rem->pack_size-pos); + pos += write_pes_header( PADDING_STREAM, rem->pack_size-pos, 0, + buf+pos, 0); + pos = rem->pack_size; + } + return pos; +} + +void print_info( Remux *rem , int ret) +{ + int newtime = 0; + static int time = 0; + int i = 0; + + while(! newtime && i < rem->vframen) { + if( (newtime = rem->vframe_list[i].time)) break; + i++; + } + if (newtime) time = newtime; + + fprintf(stderr,"SCR:"); + printpts(rem->SCR); + fprintf(stderr," VDTS:"); + printpts((uint32_t)((uint64_t)rem->vdts - rem->vpts_off + rem->vpts_delay)); + fprintf(stderr," APTS:"); + printpts((uint32_t)((uint64_t)rem->apts - rem->apts_off + rem->apts_delay)); + fprintf(stderr," TIME:%2d:", time/3600); + fprintf(stderr,"%02d:", (time%3600)/60); + fprintf(stderr,"%02d", (time%3600)%60); + if (ret) fprintf(stderr,"\n"); + else fprintf(stderr,"\r"); +} + +void remux(int fin, int fout, int pack_size, int mult) +{ + Remux rem; + long ptsdiff; + uint8_t buf[MAX_PACK_L]; + long pos = 0; + int r = 0; + int i, r1, r2; + long packets = 0; + uint8_t mpeg_end[4] = { 0x00, 0x00, 0x01, 0xB9 }; + uint32_t SCR_inc = 0; + int data_size; + long vbuf, abuf; + long vbuf_max, abuf_max; + PTS_List abufl[MAX_PTS]; + PTS_List vbufl[MAX_PTS]; + int abufn = 0; + int vbufn = 0; + uint64_t pts_d = 0; + int ok_audio; + int ok_video; + uint32_t apos = 0; + uint32_t vpos = 0; + int vpack_size = 0; + int apack_size = 0; + + init_ptsl(abufl); + init_ptsl(vbufl); + + if (mult < 0 || mult >1000){ + fprintf(stderr,"Multipler too large\n"); + exit(1); + } + init_remux(&rem, fin, fout, mult); + rem.pack_size = pack_size; + data_size = pack_size - MAX_H_SIZE; + fprintf(stderr,"pack_size: %d header_size: %d data size: %d\n", + pack_size, MAX_H_SIZE, data_size); + refill_buffy(&rem); + fprintf(stderr,"Package size: %d\n",pack_size); + + if ( get_video_info(&rem) < 0 ){ + fprintf(stderr,"ERROR: Can't find valid video stream\n"); + exit(1); + } + + i = 0; + while(! rem.time_off && i < rem.vframen) { + if( (rem.time_off = rem.vframe_list[i].time)) break; + i++; + } + + if ( get_audio_info(&rem) < 0 ){ + fprintf(stderr,"ERROR: Can't find valid audio stream\n"); + exit(1); + } + + rem.vpts = rem.vpts_list[0].PTS; + rem.vdts = rem.vpts; + rem.vpts_off = rem.vpts; + fprintf(stderr,"Video start PTS = %fs \n",rem.vpts_off/90000.); + rem.apts = rem.apts_list[0].PTS; + rem.apts_off = rem.apts; + ptsdiff = rem.vpts - rem.apts; + if (ptsdiff > 0) rem.vpts_off -= ptsdiff; + else rem.apts_off -= -ptsdiff; + fprintf(stderr,"Audio start PTS = %fs\n",rem.apts_off/90000.); + fprintf(stderr,"Difference Video - Audio = %fs\n",ptsdiff/90000.); + fprintf(stderr,"Time offset = %ds\n",rem.time_off); + + rem.muxr = (rem.video_info.bit_rate + + rem.audio_info.bit_rate)/400; + fprintf(stderr,"MUXRATE: %.2f Mb/sec\n",rem.muxr/2500.); + SCR_inc = 1800 * pack_size / rem.muxr; + + r = 0; + while ( rem.vptsn < 2 && !r) r = refill_buffy(&rem); + r = 0; + while ( rem.aptsn < 2 && !r) r = refill_buffy(&rem); + + //rem.vpts_delay = (uint32_t)(2*90000ULL* (uint64_t)pack_size/rem.muxr); + rem.vpts_delay = rem.dts_delay; + rem.apts_delay = rem.vpts_delay; + + vbuf_max = 29440; + abuf_max = 4096; + vbuf = 0; + abuf = 0; + pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, + 0xC0, 0, 32, 0xE0, 1, 230); + pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0, buf+pos,0); + pos = rem.pack_size; + write( fout, buf, pos); + + apos = rem.aread; + vpos = rem.vread; + print_info( &rem, 1 ); + + while( ring_rest(&rem.aud_buffy) && ring_rest(&rem.vid_buffy) ){ + uint32_t next_apts; + uint32_t next_vdts; + int asize, vsize; + + r1 = 0; + r2 = 0; + while ( rem.aframen < 2 && !r1) + r1 = refill_buffy(&rem); + while ( rem.vframen < 2 && !r2) + r2 = refill_buffy(&rem); + if (r1 && r2) break; + + if ( !r1 && apos <= rem.aread) + apos = rem.aframe_list[1].pos; + if ( !r2 && vpos <= rem.vread) + vpos = rem.vframe_list[1].pos; + apack_size = apos - rem.aread; + vpack_size = vpos - rem.vread; + + + next_vdts = (uint32_t)((uint64_t)rem.vdts + rem.vpts_delay + - rem.vpts_off) ; + ok_video = ( rem.SCR < next_vdts); + + next_apts = (uint32_t)((uint64_t)rem.apts + rem.apts_delay + - rem.apts_off) ; + ok_audio = ( rem.SCR < next_apts); + + asize = (apack_size > data_size ? data_size: apack_size); + vsize = (vpack_size > data_size ? data_size: vpack_size); + + fprintf(stderr,"vframen: %d aframen: %d v_ok: %d a_ok: %d v_buf: %d a_buf: %d vpacks: %d apacks: %d\n",rem.vframen,rem.aframen, ok_video, ok_audio, (int)vbuf,(int)abuf,vsize, asize); + + + if( vbuf+vsize < vbuf_max && vsize && ok_audio ){ + fprintf(stderr,"1 "); + pos = write_video_pes( &rem, buf, &vpack_size); + write( fout, buf, pos); + vbuf += vpack_size; + vbufn = add_pts( vbufl, rem.vdts, vpack_size, + 0, vbufn, 0); + packets++; + } else if ( abuf+asize < abuf_max && asize && + ok_video ){ + fprintf(stderr,"2 "); + pos = write_audio_pes( &rem, buf, &apack_size); + write( fout, buf, pos); + abuf += apack_size; + abufn = add_pts( abufl, rem.apts, apack_size, + 0, abufn, 0); + packets++; + } else if ( abuf+asize < abuf_max && asize && + !ok_audio){ + fprintf(stderr,"3 "); + pos = write_audio_pes( &rem, buf, &apack_size); + write( fout, buf, pos); + abuf += apack_size; + abufn = add_pts( abufl, rem.apts, apack_size, + 0, abufn, 0); + packets++; + } else if (vbuf+vsize < vbuf_max && vsize && + !ok_video){ + fprintf(stderr,"4 "); + pos = write_video_pes( &rem, buf, &vpack_size); + write( fout, buf, pos); + vbuf += vpack_size; + vbufn = add_pts( vbufl, rem.vdts, vpack_size, + 0, vbufn, 0); + packets++; + } else { + fprintf(stderr,"5 "); + pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0); + + pos += write_pes_header( PADDING_STREAM, pack_size-pos, + 0, buf+pos, 0); + write( fout, buf, pos); + } + + + //fprintf(stderr,"vbufn: %d abufn: %d ", vbufn,abufn); + //fprintf(stderr,"vbuf: %5d abuf: %4d\n", vbuf,abuf); + + if (rem.SCR > rem.vdts+rem.vpts_off -rem.vpts_delay) + rem.SCR = rem.vdts-rem.vpts_off; + rem.SCR = (uint32_t)((uint64_t) rem.SCR + SCR_inc); + + if ( rem.apts_off + rem.SCR < rem.apts_delay ) pts_d = 0; + else pts_d = (uint64_t) rem.SCR + rem.apts_off - rem.apts_delay; + abuf -= del_ptss( abufl, (uint32_t) pts_d, &abufn); + + if ( rem.vpts_off + rem.SCR < rem.vpts_delay ) pts_d = 0; + else pts_d = (uint64_t) rem.SCR + rem.vpts_off - rem.vpts_delay; + vbuf -= del_ptss( vbufl, (uint32_t) pts_d, &vbufn); + + print_info( &rem, 1); + //fprintf(stderr,"vbufn: %d abufn: %d ", vbufn,abufn); + //fprintf(stderr,"vbuf: %5d abuf: %4d\n\n", vbuf,abuf); + + + } + pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0); + + pos += write_pes_header( PADDING_STREAM, pack_size-pos-4, 0, + buf+pos, 0); + pos = rem.pack_size-4; + write( fout, buf, pos); + + write( fout, mpeg_end, 4); + fprintf(stderr,"\ndone\n"); +} + + +typedef +struct pes_buffer_s{ + ringbuffy pes_buffy; + uint8_t type; + PTS_List pts_list[MAX_PTS]; + FRAME_List frame_list[MAX_FRAME]; + int pes_size; + uint64_t written; + uint64_t read; +} PESBuffer; + + +void init_PESBuffer(PESBuffer *pbuf, int pes_size, int buf_size, uint8_t type) +{ + init_framel( pbuf->frame_list); + init_ptsl( pbuf->pts_list); + ring_init( &pbuf->pes_buffy, buf_size); + pbuf->pes_size = pes_size; + pbuf->type = type; + pbuf->written = 0; + pbuf->read = 0; +} + + +#define MAX_PBUF 4 + +typedef +struct remux_s{ + PESBuffer pbuf_list[MAX_PBUF]; + int num_pbuf; +} REMUX; + + +void init_REMUX(REMUX *rem) +{ + rem->num_pbuf = 0; +} + + + +#define REPACK 2048 +#define ABUF_SIZE REPACK*1024 +#define VBUF_SIZE REPACK*10240 + +void remux_main(uint8_t *buf, int count, void *pr) +{ + int i, b; + int bufsize = 0; + p2p *p = (p2p *) pr; + PESBuffer *pbuf; + REMUX *rem = (REMUX *) p->data; + uint8_t type = buf[3]; + int *npbuf = &(rem->num_pbuf); + + switch ( type ){ + case PRIVATE_STREAM1: + bufsize = ABUF_SIZE; + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + if (!bufsize) bufsize = VBUF_SIZE; + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + if (!bufsize) bufsize = ABUF_SIZE; + b = -1; + for ( i = 0; i < *npbuf; i++){ + if ( type == rem->pbuf_list[i].type ){ + b = i; + break; + } + } + if (b < 0){ + if ( *npbuf < MAX_PBUF ){ + init_PESBuffer(&rem->pbuf_list[*npbuf], + p->repack+6, bufsize, type); + b = *npbuf; + (*npbuf)++; + } else { + fprintf(stderr,"Not enough PES buffers\n"); + exit(1); + } + } + break; + default: + return; + } + + pbuf = &(rem->pbuf_list[b]); + if (ring_write(&(pbuf->pes_buffy),(char *)buf,count) != count){ + fprintf(stderr,"buffer overflow type 0x%2x\n",type); + exit(1); + } else { + pbuf->written += count; + if ((p->flag2 & PTS_DTS_FLAGS)){ + uint32_t PTS = trans_pts_dts(p->pts); + add_pts(pbuf->pts_list, PTS, pbuf->written, + pbuf->written, 0, 0); + } + p->flag2 = 0; + } + +} + +void output_mux(p2p *p) +{ + int i, filling; + PESBuffer *pbuf; + ringbuffy *pes_buffy; + REMUX *rem = (REMUX *) p->data; + int repack = p->repack; + int npbuf = rem->num_pbuf; + + for ( i = 0; i < npbuf; i++){ + pbuf = &(rem->pbuf_list[i]); + pes_buffy = &pbuf->pes_buffy; + filling = pes_buffy->size - ring_rest(pes_buffy); + if (filling/(2 *repack)){ + pbuf->read += ring_read_file(pes_buffy, p->fd1, + (filling/repack)*repack); + } + } +} + + + +#define SIZE 32768 + +void remux2(int fdin, int fdout) +{ + p2p p; + int count = 1; + uint8_t buf[SIZE]; + uint64_t length = 0; + uint64_t l = 0; + int verb = 0; + REMUX rem; + + init_p2p(&p, remux_main, REPACK); + p.fd1 = fdout; + p.data = (void *) &rem; + + + if (fdin != STDIN_FILENO) verb = 1; + + if (verb) { + length = lseek(fdin, 0, SEEK_END); + lseek(fdin,0,SEEK_SET); + } + + while (count > 0){ + count = read(fdin,buf,SIZE); + l += count; + if (verb) + fprintf(stderr,"Writing %2.2f %%\r", + 100.*l/length); + + get_pes(buf,count,&p,pes_repack); + output_mux(&p); + } + +} diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/remux.h b/plugins/streamdev/streamdev-cvs/libdvbmpeg/remux.h new file mode 100644 index 0000000..76c128b --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/remux.h @@ -0,0 +1,149 @@ +/* + * dvb-mpegtools for the Siemens Fujitsu DVB PCI card + * + * Copyright (C) 2000, 2001 Marcus Metzler + * for convergence integrated media GmbH + * Copyright (C) 2002 Marcus Metzler + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + + * The author can be reached at mocm@metzlerbros.de, + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +#include "ringbuffy.h" +#include "ctools.h" + +#ifndef _REMUX_H_ +#define _REMUX_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + typedef struct video_i{ + uint32_t horizontal_size; + uint32_t vertical_size ; + uint32_t aspect_ratio ; + double framerate ; + uint32_t video_format; + uint32_t bit_rate ; + uint32_t comp_bit_rate ; + uint32_t vbv_buffer_size; + uint32_t CSPF ; + uint32_t off; + } VideoInfo; + + typedef struct audio_i{ + int layer; + uint32_t bit_rate; + uint32_t frequency; + uint32_t mode; + uint32_t mode_extension; + uint32_t emphasis; + uint32_t framesize; + uint32_t off; + } AudioInfo; + + + + typedef + struct PTS_list_struct{ + uint32_t PTS; + int pos; + uint32_t dts; + int spos; + } PTS_List; + + typedef + struct frame_list_struct{ + int type; + int pos; + uint32_t FRAME; + uint32_t time; + uint32_t pts; + uint32_t dts; + } FRAME_List; + + typedef + struct remux_struct{ + ringbuffy vid_buffy; + ringbuffy aud_buffy; + PTS_List vpts_list[MAX_PTS]; + PTS_List apts_list[MAX_PTS]; + FRAME_List vframe_list[MAX_FRAME]; + FRAME_List aframe_list[MAX_FRAME]; + int vptsn; + int aptsn; + int vframen; + int aframen; + long apes; + long vpes; + uint32_t vframe; + uint32_t aframe; + uint32_t vcframe; + uint32_t acframe; + uint32_t vpts; + uint32_t vdts; + uint32_t apts; + uint32_t vpts_old; + uint32_t apts_old; + uint32_t SCR; + uint32_t apts_off; + uint32_t vpts_off; + uint32_t apts_delay; + uint32_t vpts_delay; + uint32_t dts_delay; + AudioInfo audio_info; + VideoInfo video_info; + int fin; + int fout; + long int awrite; + long int vwrite; + long int aread; + long int vread; + uint32_t group; + uint32_t groupframe; + uint32_t muxr; + int pack_size; + uint32_t time_off; + } Remux; + + enum { NONE, I_FRAME, P_FRAME, B_FRAME, D_FRAME }; + + void remux(int fin, int fout, int pack_size, int mult); + void remux2(int fdin, int fdout); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*_REMUX_H_*/ diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/ringbuffy.c b/plugins/streamdev/streamdev-cvs/libdvbmpeg/ringbuffy.c new file mode 100644 index 0000000..965e49a --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/ringbuffy.c @@ -0,0 +1,201 @@ +/* + Ringbuffer Implementation for gtvscreen + + Copyright (C) 2000 Marcus Metzler (mocm@metzlerbros.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "ringbuffy.h" +#include + +int ring_init (ringbuffy *rbuf, int size) +{ + if (size > 0){ + rbuf->size = size; + if( !(rbuf->buffy = (char *) malloc(sizeof(char)*size)) ){ + fprintf(stderr,"Not enough memory for ringbuffy\n"); + return -1; + } + } else { + fprintf(stderr,"Wrong size for ringbuffy\n"); + return -1; + } + rbuf->read_pos = 0; + rbuf->write_pos = 0; + return 0; +} + + +void ring_destroy(ringbuffy *rbuf) +{ + free(rbuf->buffy); +} + + +int ring_write(ringbuffy *rbuf, char *data, int count) +{ + + int diff, free, pos, rest; + + if (count <=0 ) return 0; + pos = rbuf->write_pos; + rest = rbuf->size - pos; + diff = rbuf->read_pos - pos; + free = (diff > 0) ? diff-1 : rbuf->size+diff-1; + + if ( free <= 0 ) return FULL_BUFFER; + if ( free < count ) count = free; + + if (count >= rest){ + memcpy (rbuf->buffy+pos, data, rest); + if (count - rest) + memcpy (rbuf->buffy, data+rest, count - rest); + rbuf->write_pos = count - rest; + } else { + memcpy (rbuf->buffy+pos, data, count); + rbuf->write_pos += count; + } + + return count; +} + + + + +int ring_peek(ringbuffy *rbuf, char *data, int count, long off) +{ + + int diff, free, pos, rest; + + if (count <=0 ) return 0; + pos = rbuf->read_pos+off; + rest = rbuf->size - pos ; + diff = rbuf->write_pos - pos; + free = (diff >= 0) ? diff : rbuf->size+diff; + + if ( free <= 0 ) return FULL_BUFFER; + if ( free < count ) count = free; + + if ( count < rest ){ + memcpy(data, rbuf->buffy+pos, count); + } else { + memcpy(data, rbuf->buffy+pos, rest); + if ( count - rest) + memcpy(data+rest, rbuf->buffy, count - rest); + } + + return count; +} + +int ring_read(ringbuffy *rbuf, char *data, int count) +{ + + int diff, free, pos, rest; + + if (count <=0 ) return 0; + pos = rbuf->read_pos; + rest = rbuf->size - pos; + diff = rbuf->write_pos - pos; + free = (diff >= 0) ? diff : rbuf->size+diff; + + if ( rest <= 0 ) return 0; + if ( free < count ) count = free; + + if ( count < rest ){ + memcpy(data, rbuf->buffy+pos, count); + rbuf->read_pos += count; + } else { + memcpy(data, rbuf->buffy+pos, rest); + if ( count - rest) + memcpy(data+rest, rbuf->buffy, count - rest); + rbuf->read_pos = count - rest; + } + + return count; +} + + + +int ring_write_file(ringbuffy *rbuf, int fd, int count) +{ + + int diff, free, pos, rest, rr; + + if (count <=0 ) return 0; + pos = rbuf->write_pos; + rest = rbuf->size - pos; + diff = rbuf->read_pos - pos; + free = (diff > 0) ? diff-1 : rbuf->size+diff-1; + + if ( rest <= 0 ) return 0; + if ( free < count ) count = free; + + if (count >= rest){ + rr = read (fd, rbuf->buffy+pos, rest); + if (rr == rest && count - rest) + rr += read (fd, rbuf->buffy, count - rest); + if (rr >=0) + rbuf->write_pos = (pos + rr) % rbuf->size; + } else { + rr = read (fd, rbuf->buffy+pos, count); + if (rr >=0) + rbuf->write_pos += rr; + } + + return rr; +} + + + +int ring_read_file(ringbuffy *rbuf, int fd, int count) +{ + + int diff, free, pos, rest, rr; + + if (count <=0 ) return 0; + pos = rbuf->read_pos; + rest = rbuf->size - pos; + diff = rbuf->write_pos - pos; + free = (diff >= 0) ? diff : rbuf->size+diff; + + if ( free <= 0 ) return FULL_BUFFER; + if ( free < count ) count = free; + + if (count >= rest){ + rr = write (fd, rbuf->buffy+pos, rest); + if (rr == rest && count - rest) + rr += write (fd, rbuf->buffy, count - rest); + if (rr >=0) + rbuf->read_pos = (pos + rr) % rbuf->size; + } else { + rr = write (fd, rbuf->buffy+pos, count); + if (rr >=0) + rbuf->read_pos += rr; + } + + + return rr; +} + +int ring_rest(ringbuffy *rbuf){ + int diff, free, pos, rest; + pos = rbuf->read_pos; + rest = rbuf->size - pos; + diff = rbuf->write_pos - pos; + free = (diff >= 0) ? diff : rbuf->size+diff; + + return free; +} diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/ringbuffy.h b/plugins/streamdev/streamdev-cvs/libdvbmpeg/ringbuffy.h new file mode 100644 index 0000000..16011d7 --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/ringbuffy.h @@ -0,0 +1,52 @@ +/* + Ringbuffer Implementation for gtvscreen + + Copyright (C) 2000 Marcus Metzler (mocm@metzlerbros.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef RINGBUFFY_H +#define RINGBUFFY_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define FULL_BUFFER -1000 +typedef struct ringbuffy{ + int read_pos; + int write_pos; + int size; + char *buffy; +} ringbuffy; + +int ring_init (ringbuffy *rbuf, int size); +void ring_destroy(ringbuffy *rbuf); +int ring_write(ringbuffy *rbuf, char *data, int count); +int ring_read(ringbuffy *rbuf, char *data, int count); +int ring_write_file(ringbuffy *rbuf, int fd, int count); +int ring_read_file(ringbuffy *rbuf, int fd, int count); +int ring_rest(ringbuffy *rbuf); +int ring_peek(ringbuffy *rbuf, char *data, int count, long off); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* RINGBUFFY_H */ diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/transform.c b/plugins/streamdev/streamdev-cvs/libdvbmpeg/transform.c new file mode 100644 index 0000000..c53f1fb --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/transform.c @@ -0,0 +1,2681 @@ +/* + * dvb-mpegtools for the Siemens Fujitsu DVB PCI card + * + * Copyright (C) 2000, 2001 Marcus Metzler + * for convergence integrated media GmbH + * Copyright (C) 2002 Marcus Metzler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + + * The author can be reached at marcus@convergence.de, + + * the project's page is at http://linuxtv.org/dvb/ + */ + + +#include "transform.h" +#include +#include +#include "ctools.h" + +static uint8_t tspid0[TS_SIZE] = { + 0x47, 0x40, 0x00, 0x10, 0x00, 0x00, 0xb0, 0x11, + 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x10, 0x00, 0x01, 0xe4, 0x00, 0x2a, 0xd6, 0x1a, + 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff +}; + +static uint8_t tspid1[TS_SIZE] = { + 0x47, 0x44, 0x00, 0x10, 0x00, 0x02, 0xb0, 0x1c, + 0x00, 0x01, 0xcb, 0x00, 0x00, 0xe0, 0xa0, 0xf0, + 0x05, 0x48, 0x03, 0x01, 0x00, 0x00, 0x02, 0xe0, + 0xa0, 0xf0, 0x00, 0x03, 0xe0, 0x50, 0xf0, 0x00, + 0xae, 0xea, 0x4e, 0x48, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff +}; + +// CRC32 lookup table for polynomial 0x04c11db7 +static const uint32_t crc_table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + +static uint32_t +calc_crc32 (const uint8_t *sec, uint8_t len) +{ + int i; + uint32_t crc = 0xffffffff; + + for (i = 0; i < len; i++) + crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *sec++) & 0xff]; + + return crc; +} + + +uint64_t trans_pts_dts(uint8_t *pts) +{ + uint64_t wts; + + wts = ((uint64_t)((pts[0] & 0x0E) << 5) | + ((pts[1] & 0xFC) >> 2)) << 24; + wts |= (((pts[1] & 0x03) << 6) | + ((pts[2] & 0xFC) >> 2)) << 16; + wts |= (((pts[2] & 0x02) << 6) | + ((pts[3] & 0xFE) >> 1)) << 8; + wts |= (((pts[3] & 0x01) << 7) | + ((pts[4] & 0xFE) >> 1)); + return wts; +} + + +void get_pespts(uint8_t *av_pts,uint8_t *pts) +{ + + pts[0] = 0x21 | + ((av_pts[0] & 0xC0) >>5); + pts[1] = ((av_pts[0] & 0x3F) << 2) | + ((av_pts[1] & 0xC0) >> 6); + pts[2] = 0x01 | ((av_pts[1] & 0x3F) << 2) | + ((av_pts[2] & 0x80) >> 6); + pts[3] = ((av_pts[2] & 0x7F) << 1) | + ((av_pts[3] & 0x80) >> 7); + pts[4] = 0x01 | ((av_pts[3] & 0x7F) << 1); +} + +uint16_t get_pid(uint8_t *pid) +{ + uint16_t pp = 0; + + pp = (pid[0] & PID_MASK_HI)<<8; + pp |= pid[1]; + + return pp; +} + +int write_ts_header(uint16_t pid, uint8_t *counter, int pes_start, + uint8_t *buf, uint8_t length) +{ + int i; + int c = 0; + int fill; + uint8_t tshead[4] = { 0x47, 0x00, 0x00, 0x10}; + + + fill = TS_SIZE-4-length; + if (pes_start) tshead[1] = 0x40; + if (fill) tshead[3] = 0x30; + tshead[1] |= (uint8_t)((pid & 0x1F00) >> 8); + tshead[2] |= (uint8_t)(pid & 0x00FF); + tshead[3] |= ((*counter)++ & 0x0F) ; + memcpy(buf,tshead,4); + c+=4; + + + if (fill){ + buf[4] = fill-1; + c++; + if (fill >1){ + buf[5] = 0x00; + c++; + } + for ( i = 6; i < fill+4; i++){ + buf[i] = 0xFF; + c++; + } + } + + return c; +} + + +int write_pes_header(uint8_t id,int length , long PTS, uint8_t *obuf, + int stuffing) +{ + uint8_t le[2]; + uint8_t dummy[3]; + uint8_t *pts; + uint8_t ppts[5]; + long lpts; + int c; + uint8_t headr[3] = {0x00, 0x00, 0x01}; + + lpts = htonl(PTS); + pts = (uint8_t *) &lpts; + + get_pespts(pts,ppts); + + c = 0; + memcpy(obuf+c,headr,3); + c += 3; + memcpy(obuf+c,&id,1); + c++; + + le[0] = 0; + le[1] = 0; + length -= 6+stuffing; + + le[0] |= ((uint8_t)(length >> 8) & 0xFF); + le[1] |= ((uint8_t)(length) & 0xFF); + memcpy(obuf+c,le,2); + c += 2; + + if (id == PADDING_STREAM){ + memset(obuf+c,0xff,length); + c+= length; + return c; + } + + dummy[0] = 0x80; + dummy[1] = 0; + dummy[2] = 0; + if (PTS){ + dummy[1] |= PTS_ONLY; + dummy[2] = 5+stuffing; + } + memcpy(obuf+c,dummy,3); + c += 3; + memset(obuf+c,0xFF,stuffing); + + if (PTS){ + memcpy(obuf+c,ppts,5); + c += 5; + } + + return c; +} + + +void init_p2p(p2p *p, void (*func)(uint8_t *buf, int count, void *p), + int repack){ + p->found = 0; + p->cid = 0; + p->mpeg = 0; + memset(p->buf,0,MMAX_PLENGTH); + p->done = 0; + p->fd1 = -1; + p->func = func; + p->bigend_repack = 0; + p->repack = 0; + if ( repack < MAX_PLENGTH && repack > 265 ){ + p->repack = repack-6; + p->bigend_repack = (uint16_t)htons((short) + ((repack-6) & 0xFFFF)); + } else { + fprintf(stderr, "Repack size %d is out of range\n",repack); + exit(1); + } +} + + + +void pes_repack(p2p *p) +{ + int count = 0; + int repack = p->repack; + int rest = p->plength; + uint8_t buf[MAX_PLENGTH]; + int bfill = 0; + int diff; + uint16_t length; + + if (rest < 0) { + fprintf(stderr,"Error in repack\n"); + return; + } + + if (!repack){ + fprintf(stderr,"forgot to set repack size\n"); + return; + } + + if (p->plength == repack){ + memcpy(p->buf+4,(char *)&p->bigend_repack,2); + p->func(p->buf, repack+6, p); + return; + } + + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x01; + buf[3] = p->cid; + memcpy(buf+4,(char *)&p->bigend_repack,2); + memset(buf+6,0,MAX_PLENGTH-6); + + if (p->mpeg == 2){ + + if ( rest > repack){ + memcpy(p->buf+4,(char *)&p->bigend_repack,2); + p->func(p->buf, repack+6, p); + count += repack+6; + rest -= repack; + } else { + memcpy(buf,p->buf,9+p->hlength); + bfill = p->hlength; + count += 9+p->hlength; + rest -= p->hlength+3; + } + + while (rest >= repack-3){ + memset(buf+6,0,MAX_PLENGTH-6); + buf[6] = 0x80; + buf[7] = 0x00; + buf[8] = 0x00; + memcpy(buf+9,p->buf+count,repack-3); + rest -= repack-3; + count += repack-3; + p->func(buf, repack+6, p); + } + + if (rest){ + diff = repack - 3 - rest - bfill; + if (!bfill){ + buf[6] = 0x80; + buf[7] = 0x00; + buf[8] = 0x00; + } + + if ( diff < PES_MIN){ + length = rest+ diff + bfill+3; + buf[4] = (uint8_t)((length & 0xFF00) >> 8); + buf[5] = (uint8_t)(length & 0x00FF); + buf[8] = (uint8_t)(bfill+diff); + memset(buf+9+bfill,0xFF,diff); + memcpy(buf+9+bfill+diff,p->buf+count,rest); + } else { + length = rest+ bfill+3; + buf[4] = (uint8_t)((length & 0xFF00) >> 8); + buf[5] = (uint8_t)(length & 0x00FF); + memcpy(buf+9+bfill,p->buf+count,rest); + bfill += rest+9; + write_pes_header( PADDING_STREAM, diff, 0, + buf+bfill, 0); + } + p->func(buf, repack+6, p); + } + } + + if (p->mpeg == 1){ + + if ( rest > repack){ + memcpy(p->buf+4,(char *)&p->bigend_repack,2); + p->func(p->buf, repack+6, p); + count += repack+6; + rest -= repack; + } else { + memcpy(buf,p->buf,6+p->hlength); + bfill = p->hlength; + count += 6; + rest -= p->hlength; + } + + while (rest >= repack-1){ + memset(buf+6,0,MAX_PLENGTH-6); + buf[6] = 0x0F; + memcpy(buf+7,p->buf+count,repack-1); + rest -= repack-1; + count += repack-1; + p->func(buf, repack+6, p); + } + + + if (rest){ + diff = repack - 1 - rest - bfill; + + if ( diff < PES_MIN){ + length = rest+ diff + bfill+1; + buf[4] = (uint8_t)((length & 0xFF00) >> 8); + buf[5] = (uint8_t)(length & 0x00FF); + memset(buf+6,0xFF,diff); + if (!bfill){ + buf[6+diff] = 0x0F; + } + memcpy(buf+7+diff,p->buf+count,rest+bfill); + } else { + length = rest+ bfill+1; + buf[4] = (uint8_t)((length & 0xFF00) >> 8); + buf[5] = (uint8_t)(length & 0x00FF); + if (!bfill){ + buf[6] = 0x0F; + memcpy(buf+7,p->buf+count,rest); + bfill = rest+7; + } else { + memcpy(buf+6,p->buf+count,rest+bfill); + bfill += rest+6; + } + write_pes_header( PADDING_STREAM, diff, 0, + buf+bfill, 0); + } + p->func(buf, repack+6, p); + } + } +} + + + + + + + + +int filter_pes (uint8_t *buf, int count, p2p *p, int (*func)(p2p *p)) +{ + + int l; + unsigned short *pl; + int c=0; + int ret = 1; + + uint8_t headr[3] = { 0x00, 0x00, 0x01} ; + + while (c < count && (p->mpeg == 0 || + (p->mpeg == 1 && p->found < 7) || + (p->mpeg == 2 && p->found < 9)) + && (p->found < 5 || !p->done)){ + switch ( p->found ){ + case 0: + case 1: + if (buf[c] == 0x00) p->found++; + else { + if (p->fd1 >= 0) + write(p->fd1,buf+c,1); + p->found = 0; + } + c++; + break; + case 2: + if (buf[c] == 0x01) p->found++; + else if (buf[c] == 0){ + p->found = 2; + } else { + if (p->fd1 >= 0) + write(p->fd1,buf+c,1); + p->found = 0; + } + c++; + break; + case 3: + p->cid = 0; + switch (buf[c]){ + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + if (p->fd1 >= 0) + write(p->fd1,buf+c,1); + p->done = 1; + case PRIVATE_STREAM1: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + p->found++; + p->cid = buf[c]; + c++; + break; + default: + if (p->fd1 >= 0) + write(p->fd1,buf+c,1); + p->found = 0; + break; + } + break; + + + case 4: + if (count-c > 1){ + pl = (unsigned short *) (buf+c); + p->plength = ntohs(*pl); + p->plen[0] = buf[c]; + c++; + p->plen[1] = buf[c]; + c++; + p->found+=2; + } else { + p->plen[0] = buf[c]; + p->found++; + return 1; + } + break; + case 5: + p->plen[1] = buf[c]; + c++; + pl = (unsigned short *) p->plen; + p->plength = ntohs(*pl); + p->found++; + break; + + + case 6: + if (!p->done){ + p->flag1 = buf[c]; + c++; + p->found++; + if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2; + else { + p->hlength = 0; + p->which = 0; + p->mpeg = 1; + p->flag2 = 0; + } + } + break; + + case 7: + if ( !p->done && p->mpeg == 2){ + p->flag2 = buf[c]; + c++; + p->found++; + } + break; + + case 8: + if ( !p->done && p->mpeg == 2){ + p->hlength = buf[c]; + c++; + p->found++; + } + break; + + default: + + break; + } + } + + if (!p->plength) p->plength = MMAX_PLENGTH-6; + + + if ( p->done || ((p->mpeg == 2 && p->found >= 9) || + (p->mpeg == 1 && p->found >= 7)) ){ + switch (p->cid){ + + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case PRIVATE_STREAM1: + + memcpy(p->buf, headr, 3); + p->buf[3] = p->cid; + memcpy(p->buf+4,p->plen,2); + + if (p->mpeg == 2 && p->found == 9){ + p->buf[6] = p->flag1; + p->buf[7] = p->flag2; + p->buf[8] = p->hlength; + } + + if (p->mpeg == 1 && p->found == 7){ + p->buf[6] = p->flag1; + } + + + if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) && + p->found < 14){ + while (c < count && p->found < 14){ + p->pts[p->found-9] = buf[c]; + p->buf[p->found] = buf[c]; + c++; + p->found++; + } + if (c == count) return 1; + } + + if (p->mpeg == 1 && p->which < 2000){ + + if (p->found == 7) { + p->check = p->flag1; + p->hlength = 1; + } + + while (!p->which && c < count && + p->check == 0xFF){ + p->check = buf[c]; + p->buf[p->found] = buf[c]; + c++; + p->found++; + p->hlength++; + } + + if ( c == count) return 1; + + if ( (p->check & 0xC0) == 0x40 && !p->which){ + p->check = buf[c]; + p->buf[p->found] = buf[c]; + c++; + p->found++; + p->hlength++; + + p->which = 1; + if ( c == count) return 1; + p->check = buf[c]; + p->buf[p->found] = buf[c]; + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return 1; + } + + if (p->which == 1){ + p->check = buf[c]; + p->buf[p->found] = buf[c]; + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return 1; + } + + if ( (p->check & 0x30) && p->check != 0xFF){ + p->flag2 = (p->check & 0xF0) << 2; + p->pts[0] = p->check; + p->which = 3; + } + + if ( c == count) return 1; + if (p->which > 2){ + if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_ONLY){ + while (c < count && + p->which < 7){ + p->pts[p->which-2] = + buf[c]; + p->buf[p->found] = + buf[c]; + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return 1; + } else if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_DTS){ + while (c < count && + p->which< 12){ + if (p->which< 7) + p->pts[p->which + -2] = + buf[c]; + p->buf[p->found] = + buf[c]; + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return 1; + } + p->which = 2000; + } + + } + + while (c < count && p->found < p->plength+6){ + l = count -c; + if (l+p->found > p->plength+6) + l = p->plength+6-p->found; + memcpy(p->buf+p->found, buf+c, l); + p->found += l; + c += l; + } + if(p->found == p->plength+6){ + if (func(p)){ + if (p->fd1 >= 0){ + write(p->fd1,p->buf, + p->plength+6); + } + } else ret = 0; + } + break; + } + + + if ( p->done ){ + if( p->found + count - c < p->plength+6){ + p->found += count-c; + c = count; + } else { + c += p->plength+6 - p->found; + p->found = p->plength+6; + } + } + + if (p->plength && p->found == p->plength+6) { + p->found = 0; + p->done = 0; + p->plength = 0; + memset(p->buf, 0, MAX_PLENGTH); + if (c < count) + return filter_pes(buf+c, count-c, p, func); + } + } + return ret; +} + + +#define SIZE 4096 + + +int audio_pes_filt(p2p *p) +{ + uint8_t off; + + switch(p->cid){ + case PRIVATE_STREAM1: + if ( p->cid == p->filter) { + off = 9+p->buf[8]; + if (p->buf[off] == p->subid){ + return 1; + } + } + break; + + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + if ( p->cid == p->filter) + return 1; + break; + + default: + return 1; + break; + } + return 0; +} + + +void filter_audio_from_pes(int fdin, int fdout, uint8_t id, uint8_t subid) +{ + p2p p; + int count = 1; + uint8_t buf[2048]; + + init_p2p(&p, NULL, 2048); + p.fd1 = -1; + p.filter = id; + p.subid = subid; + + while (count > 0){ + count = read(fdin,buf,2048); + if(filter_pes(buf,count,&p,audio_pes_filt)) + write(fdout,buf,2048); + } +} + + +void pes_filt(p2p *p) +{ + int factor = p->mpeg-1; + + if ( p->cid == p->filter) { + if (p->es) + write(p->fd1,p->buf+p->hlength+6+3*factor, + p->plength-p->hlength-3*factor); + else + write(p->fd1,p->buf,p->plength+6); + } +} + +void extract_from_pes(int fdin, int fdout, uint8_t id, int es) +{ + p2p p; + int count = 1; + uint8_t buf[SIZE]; + + init_p2p(&p, NULL, 2048); + p.fd1 = fdout; + p.filter = id; + p.es = es; + + while (count > 0){ + count = read(fdin,buf,SIZE); + get_pes(buf,count,&p,pes_filt); + } +} + + +void pes_dfilt(p2p *p) +{ + int factor = p->mpeg-1; + int fd =0; + int head=0; + int type = NOPES; + int streamid; + int c = 6+p->hlength+3*factor; + + + switch ( p->cid ) { + case PRIVATE_STREAM1: + streamid = p->buf[c]; + head = 4; + if ((streamid & 0xF8) == 0x80+p->es-1){ + fd = p->fd1; + type = AC3; + } + break; + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + fd = p->fd1; + type = AUDIO; + break; + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + fd = p->fd2; + type = VIDEO; + break; + } + + if (p->es && !p->startv && type == VIDEO){ + int found = 0; + + if ( p->flag2 & PTS_DTS ) + p->vpts = trans_pts_dts(p->pts); + else return; + + while ( !found && c+3 < p->plength+6 ){ + if ( p->buf[c] == 0x00 && + p->buf[c+1] == 0x00 && + p->buf[c+2] == 0x01 && + p->buf[c+3] == 0xb3) + found = 1; + else c++; + } + if (found){ + p->startv = 1; + write(fd, p->buf+c, p->plength+6-c); + } + fd = 0; + } + + + if ( p->es && !p->starta && type == AUDIO){ + int found = 0; + if ( p->flag2 & PTS_DTS ) + p->apts = trans_pts_dts(p->pts); + else return; + + if (p->startv) + while ( !found && c+1 < p->plength+6){ + if ( p->buf[c] == 0xFF && + (p->buf[c+1] & 0xF8) == 0xF8) + found = 1; + else c++; + } + if (found){ + p->starta = 1; + write(fd, p->buf+c, p->plength+6-c); + } + fd = 0; + } + + if ( p->es && !p->starta && type == AC3){ + if ( p->flag2 & PTS_DTS ) + p->apts = trans_pts_dts(p->pts); + else return; + + if (p->startv){ + c+= ((p->buf[c+2] << 8)| p->buf[c+3]); + p->starta = 1; + write(fd, p->buf+c, p->plength+6-c); + } + fd = 0; + } + + + if (fd){ + if (p->es) + write(fd,p->buf+p->hlength+6+3*factor+head, + p->plength-p->hlength-3*factor-head); + else + write(fd,p->buf,p->plength+6); + } +} + +int64_t pes_dmx( int fdin, int fdouta, int fdoutv, int es) +{ + p2p p; + int count = 1; + uint8_t buf[SIZE]; + uint64_t length = 0; + uint64_t l = 0; + int verb = 0; + int percent, oldPercent = -1; + + init_p2p(&p, NULL, 2048); + p.fd1 = fdouta; + p.fd2 = fdoutv; + p.es = es; + p.startv = 0; + p.starta = 0; + p.apts=-1; + p.vpts=-1; + + if (fdin != STDIN_FILENO) verb = 1; + + if (verb) { + length = lseek(fdin, 0, SEEK_END); + lseek(fdin,0,SEEK_SET); + } + + while (count > 0){ + count = read(fdin,buf,SIZE); + l += count; + if (verb){ + percent = 100 * l / length; + + if (percent != oldPercent) { + fprintf(stderr, "Demuxing %d %%\r", percent); + oldPercent = percent; + } + } + get_pes(buf,count,&p,pes_dfilt); + } + + return (int64_t)p.vpts - (int64_t)p.apts; + +} + + +/* SV: made non-static */ +void pes_in_ts(p2p *p) +{ + int l, pes_start; + uint8_t obuf[TS_SIZE]; + long int c = 0; + int length = p->plength+6; + uint16_t pid; + uint8_t *counter; + pes_start = 1; + switch ( p->cid ) { + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + pid = p->pida; + counter = &p->acounter; + break; + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + pid = p->pidv; + counter = &p->acounter; + + tspid0[3] |= (p->count0++) + & 0x0F ; + tspid1[3] |= (p->count1++) + & 0x0F ; + + tspid1[24] = p->pidv; + tspid1[23] |= (p->pidv >> 8) & 0x3F; + tspid1[29] = p->pida; + tspid1[28] |= (p->pida >> 8) & 0x3F; + + p->func(tspid0,188,p); + p->func(tspid1,188,p); + break; + default: + return; + } + + while ( c < length ){ + memset(obuf,0,TS_SIZE); + if (length - c >= TS_SIZE-4){ + l = write_ts_header(pid, counter, pes_start + , obuf, TS_SIZE-4); + memcpy(obuf+l, p->buf+c, TS_SIZE-l); + c += TS_SIZE-l; + } else { + l = write_ts_header(pid, counter, pes_start + , obuf, length-c); + memcpy(obuf+l, p->buf+c, TS_SIZE-l); + c = length; + } + p->func(obuf,188,p); + pes_start = 0; + } +} + +static +void write_out(uint8_t *buf, int count,void *p) +{ + write(STDOUT_FILENO, buf, count); +} + + +void pes_to_ts2( int fdin, int fdout, uint16_t pida, uint16_t pidv) +{ + p2p p; + int count = 1; + uint8_t buf[SIZE]; + uint64_t length = 0; + uint64_t l = 0; + int verb = 0; + + init_p2p(&p, NULL, 2048); + p.fd1 = fdout; + p.pida = pida; + p.pidv = pidv; + p.acounter = 0; + p.vcounter = 0; + p.count1 = 0; + p.count0 = 0; + p.func = write_out; + + if (fdin != STDIN_FILENO) verb = 1; + + if (verb) { + length = lseek(fdin, 0, SEEK_END); + lseek(fdin,0,SEEK_SET); + } + + while (count > 0){ + count = read(fdin,buf,SIZE); + l += count; + if (verb) + fprintf(stderr,"Writing TS %2.2f %%\r", + 100.*l/length); + + get_pes(buf,count,&p,pes_in_ts); + } + +} + + +#define IN_SIZE TS_SIZE*10 +void find_avpids(int fd, uint16_t *vpid, uint16_t *apid) +{ + uint8_t buf[IN_SIZE]; + int count; + int i; + int off =0; + + while ( *apid == 0 || *vpid == 0){ + count = read(fd, buf, IN_SIZE); + for (i = 0; i < count-7; i++){ + if (buf[i] == 0x47){ + if (buf[i+1] & 0x40){ + off = 0; + if ( buf[3+i] & 0x20)//adapt field? + off = buf[4+i] + 1; + switch(buf[i+7+off]){ + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + *vpid = get_pid(buf+i+1); + break; + case PRIVATE_STREAM1: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + *apid = get_pid(buf+i+1); + break; + } + } + i += 187; + } + if (*apid != 0 && *vpid != 0) break; + } + } +} + +void find_bavpids(uint8_t *buf, int count, uint16_t *vpid, uint16_t *apid) +{ + int i; + int founda = 0; + int foundb = 0; + int off = 0; + + *vpid = 0; + *apid = 0; + for (i = 0; i < count-7; i++){ + if (buf[i] == 0x47){ + if ((buf[i+1] & 0xF0) == 0x40){ + off = 0; + if ( buf[3+i] & 0x20) // adaptation field? + off = buf[4+i] + 1; + + if (buf[off+i+4] == 0x00 && + buf[off+i+5] == 0x00 && + buf[off+i+6] == 0x01){ + switch(buf[off+i+7]){ + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + *vpid = get_pid(buf+i+1); + foundb=1; + break; + case PRIVATE_STREAM1: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + *apid = get_pid(buf+i+1); + founda=1; + break; + } + } + } + i += 187; + } + if (founda && foundb) break; + } +} + + +void ts_to_pes( int fdin, uint16_t pida, uint16_t pidv, int ps) +{ + + uint8_t buf[IN_SIZE]; + uint8_t mbuf[TS_SIZE]; + int i; + int count = 1; + uint16_t pid; + uint16_t dummy; + ipack pa, pv; + ipack *p; + + if (fdin != STDIN_FILENO && (!pida || !pidv)) + find_avpids(fdin, &pidv, &pida); + + init_ipack(&pa, IPACKS,write_out, ps); + init_ipack(&pv, IPACKS,write_out, ps); + + if ((count = save_read(fdin,mbuf,TS_SIZE))<0) + perror("reading"); + + for ( i = 0; i < 188 ; i++){ + if ( mbuf[i] == 0x47 ) break; + } + if ( i == 188){ + fprintf(stderr,"Not a TS\n"); + return; + } else { + memcpy(buf,mbuf+i,TS_SIZE-i); + if ((count = save_read(fdin,mbuf,i))<0) + perror("reading"); + memcpy(buf+TS_SIZE-i,mbuf,i); + i = 188; + } + count = 1; + while (count > 0){ + if ((count = save_read(fdin,buf+i,IN_SIZE-i)+i)<0) + perror("reading"); + + + if (!pidv){ + find_bavpids(buf+i, IN_SIZE-i, &pidv, &dummy); + if (pidv) fprintf(stderr, "vpid %d (0x%02x)\n", + pidv,pidv); + } + + if (!pida){ + find_bavpids(buf+i, IN_SIZE-i, &dummy, &pida); + if (pida) fprintf(stderr, "apid %d (0x%02x)\n", + pida,pida); + } + + + for( i = 0; i < count; i+= TS_SIZE){ + uint8_t off = 0; + + if ( count - i < TS_SIZE) break; + + pid = get_pid(buf+i+1); + if (!(buf[3+i]&0x10)) // no payload? + continue; + if ( buf[1+i]&0x80){ + fprintf(stderr,"Error in TS for PID: %d\n", + pid); + } + if (pid == pidv){ + p = &pv; + } else { + if (pid == pida){ + p = &pa; + } else continue; + } + + if ( buf[1+i]&0x40) { + if (p->plength == MMAX_PLENGTH-6){ + p->plength = p->found-6; + p->found = 0; + send_ipack(p); + reset_ipack(p); + } + } + + if ( buf[3+i] & 0x20) { // adaptation field? + off = buf[4+i] + 1; + } + + instant_repack(buf+4+off+i, TS_SIZE-4-off, p); + } + i = 0; + + } + +} + + +#define INN_SIZE 2*IN_SIZE +void insert_pat_pmt( int fdin, int fdout) +{ + + uint8_t buf[INN_SIZE]; + uint8_t mbuf[TS_SIZE]; + int i; + int count = 1; + uint16_t pida = 0; + uint16_t pidv = 0; + int written,c; + uint8_t c0 = 0; + uint8_t c1 = 0; + uint8_t pmt_len; + uint32_t crc32; + + + find_avpids(fdin, &pidv, &pida); + + count = save_read(fdin,mbuf,TS_SIZE); + for ( i = 0; i < 188 ; i++){ + if ( mbuf[i] == 0x47 ) break; + } + if ( i == 188){ + fprintf(stderr,"Not a TS\n"); + return; + } else { + memcpy(buf,mbuf+i,TS_SIZE-i); + count = save_read(fdin,mbuf,i); + memcpy(buf+TS_SIZE-i,mbuf,i); + i = 188; + } + + count = 1; + /* length is not correct, but we only create a very small + * PMT, so it doesn't matter :-) + */ + pmt_len = tspid1[7] + 3; + while (count > 0){ + tspid1[24] = pidv; + tspid1[23] |= (pidv >> 8) & 0x3F; + tspid1[29] = pida; + tspid1[28] |= (pida >> 8) & 0x3F; + crc32 = calc_crc32 (&tspid1[5], pmt_len - 4); + tspid1[5 + pmt_len - 4] = (crc32 & 0xff000000) >> 24; + tspid1[5 + pmt_len - 3] = (crc32 & 0x00ff0000) >> 16; + tspid1[5 + pmt_len - 2] = (crc32 & 0x0000ff00) >> 8; + tspid1[5 + pmt_len - 1] = (crc32 & 0x000000ff) >> 0; + + write(fdout,tspid0,188); + write(fdout,tspid1,188); + + count = save_read(fdin,buf+i,INN_SIZE-i); + + written = 0; + while (written < IN_SIZE){ + c = write(fdout,buf,INN_SIZE); + if (c>0) written += c; + } + tspid0[3] &= 0xF0 ; + tspid0[3] |= (c0++)& 0x0F ; + + tspid1[3] &= 0xF0 ; + tspid1[3] |= (c1++)& 0x0F ; + + i=0; + } + +} + +void get_pes (uint8_t *buf, int count, p2p *p, void (*func)(p2p *p)) +{ + + int l; + unsigned short *pl; + int c=0; + + uint8_t headr[3] = { 0x00, 0x00, 0x01} ; + + while (c < count && (p->mpeg == 0 || + (p->mpeg == 1 && p->found < 7) || + (p->mpeg == 2 && p->found < 9)) + && (p->found < 5 || !p->done)){ + switch ( p->found ){ + case 0: + case 1: + if (buf[c] == 0x00) p->found++; + else p->found = 0; + c++; + break; + case 2: + if (buf[c] == 0x01) p->found++; + else if (buf[c] == 0){ + p->found = 2; + } else p->found = 0; + c++; + break; + case 3: + p->cid = 0; + switch (buf[c]){ + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + p->done = 1; + case PRIVATE_STREAM1: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + p->found++; + p->cid = buf[c]; + c++; + break; + default: + p->found = 0; + break; + } + break; + + + case 4: + if (count-c > 1){ + pl = (unsigned short *) (buf+c); + p->plength = ntohs(*pl); + p->plen[0] = buf[c]; + c++; + p->plen[1] = buf[c]; + c++; + p->found+=2; + } else { + p->plen[0] = buf[c]; + p->found++; + return; + } + break; + case 5: + p->plen[1] = buf[c]; + c++; + pl = (unsigned short *) p->plen; + p->plength = ntohs(*pl); + p->found++; + break; + + + case 6: + if (!p->done){ + p->flag1 = buf[c]; + c++; + p->found++; + if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2; + else { + p->hlength = 0; + p->which = 0; + p->mpeg = 1; + p->flag2 = 0; + } + } + break; + + case 7: + if ( !p->done && p->mpeg == 2){ + p->flag2 = buf[c]; + c++; + p->found++; + } + break; + + case 8: + if ( !p->done && p->mpeg == 2){ + p->hlength = buf[c]; + c++; + p->found++; + } + break; + + default: + + break; + } + } + + if (!p->plength) p->plength = MMAX_PLENGTH-6; + + + if ( p->done || ((p->mpeg == 2 && p->found >= 9) || + (p->mpeg == 1 && p->found >= 7)) ){ + switch (p->cid){ + + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case PRIVATE_STREAM1: + + memcpy(p->buf, headr, 3); + p->buf[3] = p->cid; + memcpy(p->buf+4,p->plen,2); + + if (p->mpeg == 2 && p->found == 9){ + p->buf[6] = p->flag1; + p->buf[7] = p->flag2; + p->buf[8] = p->hlength; + } + + if (p->mpeg == 1 && p->found == 7){ + p->buf[6] = p->flag1; + } + + + if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) && + p->found < 14){ + while (c < count && p->found < 14){ + p->pts[p->found-9] = buf[c]; + p->buf[p->found] = buf[c]; + c++; + p->found++; + } + if (c == count) return; + } + + if (p->mpeg == 1 && p->which < 2000){ + + if (p->found == 7) { + p->check = p->flag1; + p->hlength = 1; + } + + while (!p->which && c < count && + p->check == 0xFF){ + p->check = buf[c]; + p->buf[p->found] = buf[c]; + c++; + p->found++; + p->hlength++; + } + + if ( c == count) return; + + if ( (p->check & 0xC0) == 0x40 && !p->which){ + p->check = buf[c]; + p->buf[p->found] = buf[c]; + c++; + p->found++; + p->hlength++; + + p->which = 1; + if ( c == count) return; + p->check = buf[c]; + p->buf[p->found] = buf[c]; + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return; + } + + if (p->which == 1){ + p->check = buf[c]; + p->buf[p->found] = buf[c]; + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return; + } + + if ( (p->check & 0x30) && p->check != 0xFF){ + p->flag2 = (p->check & 0xF0) << 2; + p->pts[0] = p->check; + p->which = 3; + } + + if ( c == count) return; + if (p->which > 2){ + if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_ONLY){ + while (c < count && + p->which < 7){ + p->pts[p->which-2] = + buf[c]; + p->buf[p->found] = + buf[c]; + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return; + } else if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_DTS){ + while (c < count && + p->which< 12){ + if (p->which< 7) + p->pts[p->which + -2] = + buf[c]; + p->buf[p->found] = + buf[c]; + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return; + } + p->which = 2000; + } + + } + + while (c < count && p->found < p->plength+6){ + l = count -c; + if (l+p->found > p->plength+6) + l = p->plength+6-p->found; + memcpy(p->buf+p->found, buf+c, l); + p->found += l; + c += l; + } + if(p->found == p->plength+6) + func(p); + + break; + } + + + if ( p->done ){ + if( p->found + count - c < p->plength+6){ + p->found += count-c; + c = count; + } else { + c += p->plength+6 - p->found; + p->found = p->plength+6; + } + } + + if (p->plength && p->found == p->plength+6) { + p->found = 0; + p->done = 0; + p->plength = 0; + memset(p->buf, 0, MAX_PLENGTH); + if (c < count) + get_pes(buf+c, count-c, p, func); + } + } + return; +} + + + + +void setup_pes2ts( p2p *p, uint32_t pida, uint32_t pidv, + void (*ts_write)(uint8_t *buf, int count, void *p)) +{ + init_p2p( p, ts_write, 2048); + p->pida = pida; + p->pidv = pidv; + p->acounter = 0; + p->vcounter = 0; + p->count1 = 0; + p->count0 = 0; +} + +void kpes_to_ts( p2p *p,uint8_t *buf ,int count ) +{ + get_pes(buf,count, p,pes_in_ts); +} + + +void setup_ts2pes( p2p *pa, p2p *pv, uint32_t pida, uint32_t pidv, + void (*pes_write)(uint8_t *buf, int count, void *p)) +{ + init_p2p( pa, pes_write, 2048); + init_p2p( pv, pes_write, 2048); + pa->pid = pida; + pv->pid = pidv; +} + +void kts_to_pes( p2p *p, uint8_t *buf) // don't need count (=188) +{ + uint8_t off = 0; + uint16_t pid = 0; + + if (!(buf[3]&PAYLOAD)) // no payload? + return; + + pid = get_pid(buf+1); + + if (pid != p->pid) return; + if ( buf[1]&0x80){ + fprintf(stderr,"Error in TS for PID: %d\n", + pid); + } + + if ( buf[1]&PAY_START) { + if (p->plength == MMAX_PLENGTH-6){ + p->plength = p->found-6; + p->found = 0; + pes_repack(p); + } + } + + if ( buf[3] & ADAPT_FIELD) { // adaptation field? + off = buf[4] + 1; + if (off+4 > 187) return; + } + + get_pes(buf+4+off, TS_SIZE-4-off, p , pes_repack); +} + + + + +// instant repack + + +void reset_ipack(ipack *p) +{ + p->found = 0; + p->cid = 0; + p->plength = 0; + p->flag1 = 0; + p->flag2 = 0; + p->hlength = 0; + p->mpeg = 0; + p->check = 0; + p->which = 0; + p->done = 0; + p->count = 0; + p->size = p->size_orig; +} + +void init_ipack(ipack *p, int size, + void (*func)(uint8_t *buf, int size, void *priv), int ps) +{ + if ( !(p->buf = malloc(size)) ){ + fprintf(stderr,"Couldn't allocate memory for ipack\n"); + exit(1); + } + p->ps = ps; + p->size_orig = size; + p->func = func; + reset_ipack(p); + p->has_ai = 0; + p->has_vi = 0; + p->start = 0; +} + +void free_ipack(ipack * p) +{ + if (p->buf) free(p->buf); +} + + + +int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr) +{ + uint8_t *headr; + int found = 0; + int sw; + int form = -1; + int c = 0; + + while (found < 4 && c+4 < count){ + uint8_t *b; + + b = mbuf+c; + if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01 + && b[3] == 0xb3) found = 4; + else { + c++; + } + } + + if (! found) return -1; + c += 4; + if (c+12 >= count) return -1; + headr = mbuf+c; + + vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4); + vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]); + + sw = (int)((headr[3]&0xF0) >> 4) ; + + switch( sw ){ + case 1: + if (pr) + fprintf(stderr,"Videostream: ASPECT: 1:1"); + vi->aspect_ratio = 100; + break; + case 2: + if (pr) + fprintf(stderr,"Videostream: ASPECT: 4:3"); + vi->aspect_ratio = 133; + break; + case 3: + if (pr) + fprintf(stderr,"Videostream: ASPECT: 16:9"); + vi->aspect_ratio = 177; + break; + case 4: + if (pr) + fprintf(stderr,"Videostream: ASPECT: 2.21:1"); + vi->aspect_ratio = 221; + break; + + case 5 ... 15: + if (pr) + fprintf(stderr,"Videostream: ASPECT: reserved"); + vi->aspect_ratio = 0; + break; + + default: + vi->aspect_ratio = 0; + return -1; + } + + if (pr) + fprintf(stderr," Size = %dx%d",vi->horizontal_size, + vi->vertical_size); + + sw = (int)(headr[3]&0x0F); + + switch ( sw ) { + case 1: + if (pr) + fprintf(stderr," FRate: 23.976 fps"); + vi->framerate = 24000/1001.; + form = -1; + break; + case 2: + if (pr) + fprintf(stderr," FRate: 24 fps"); + vi->framerate = 24; + form = -1; + break; + case 3: + if (pr) + fprintf(stderr," FRate: 25 fps"); + vi->framerate = 25; + form = VIDEO_MODE_PAL; + break; + case 4: + if (pr) + fprintf(stderr," FRate: 29.97 fps"); + vi->framerate = 30000/1001.; + form = VIDEO_MODE_NTSC; + break; + case 5: + if (pr) + fprintf(stderr," FRate: 30 fps"); + vi->framerate = 30; + form = VIDEO_MODE_NTSC; + break; + case 6: + if (pr) + fprintf(stderr," FRate: 50 fps"); + vi->framerate = 50; + form = VIDEO_MODE_PAL; + break; + case 7: + if (pr) + fprintf(stderr," FRate: 60 fps"); + vi->framerate = 60; + form = VIDEO_MODE_NTSC; + break; + } + + vi->bit_rate = 400*(((headr[4] << 10) & 0x0003FC00UL) + | ((headr[5] << 2) & 0x000003FCUL) | + (((headr[6] & 0xC0) >> 6) & 0x00000003UL)); + + if (pr){ + fprintf(stderr," BRate: %.2f Mbit/s",(vi->bit_rate)/1000000.); + fprintf(stderr,"\n"); + } + vi->video_format = form; + + vi->off = c-4; + return c-4; +} + +extern unsigned int bitrates[3][16]; +extern uint32_t freq[4]; + +int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr) +{ + uint8_t *headr; + int found = 0; + int c = 0; + int fr =0; + + while (!found && c < count){ + uint8_t *b = mbuf+c; + + if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8) + found = 1; + else { + c++; + } + } + + if (!found) return -1; + + if (c+3 >= count) return -1; + headr = mbuf+c; + + ai->layer = (headr[1] & 0x06) >> 1; + + if (pr) + fprintf(stderr,"Audiostream: Layer: %d", 4-ai->layer); + + + ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000; + + if (pr){ + if (ai->bit_rate == 0) + fprintf (stderr," Bit rate: free"); + else if (ai->bit_rate == 0xf) + fprintf (stderr," BRate: reserved"); + else + fprintf (stderr," BRate: %d kb/s", ai->bit_rate/1000); + } + + fr = (headr[2] & 0x0c ) >> 2; + ai->frequency = freq[fr]*100; + + if (pr){ + if (ai->frequency == 3) + fprintf (stderr, " Freq: reserved\n"); + else + fprintf (stderr," Freq: %2.1f kHz\n", + ai->frequency/1000.); + } + ai->off = c; + return c; +} + +unsigned int ac3_bitrates[32] = + {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640, + 0,0,0,0,0,0,0,0,0,0,0,0,0}; + +uint32_t ac3_freq[4] = {480, 441, 320, 0}; +uint32_t ac3_frames[3][32] = + {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024, + 1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114, + 1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344, + 1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}}; + +int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr) +{ + uint8_t *headr; + int found = 0; + int c = 0; + uint8_t frame; + int fr = 0; + + while ( !found && c < count){ + uint8_t *b = mbuf+c; + if ( b[0] == 0x0b && b[1] == 0x77 ) + found = 1; + else { + c++; + } + } + + + if (!found){ + return -1; + } + ai->off = c; + + if (c+5 >= count) return -1; + + ai->layer = 0; // 0 for AC3 + headr = mbuf+c+2; + + frame = (headr[2]&0x3f); + ai->bit_rate = ac3_bitrates[frame>>1]*1000; + + if (pr) fprintf (stderr," BRate: %d kb/s", ai->bit_rate/1000); + + fr = (headr[2] & 0xc0 ) >> 6; + ai->frequency = freq[fr]*100; + if (pr) fprintf (stderr," Freq: %d Hz\n", ai->frequency); + + ai->framesize = ac3_frames[fr][frame >> 1]; + if ((frame & 1) && (fr == 1)) ai->framesize++; + ai->framesize = ai->framesize << 1; + if (pr) fprintf (stderr," Framesize %d\n", ai->framesize); + + return c; +} + + +void ps_pes(ipack *p) +{ + int check; + uint8_t pbuf[PS_HEADER_L2]; + static int muxr = 0; + static int ai = 0; + static int vi = 0; + static int start = 0; + static uint32_t SCR = 0; + + if (p->mpeg == 2){ + switch(p->buf[3]){ + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + if (!p->has_vi){ + if(get_vinfo(p->buf, p->count, &p->vi,1) >=0) { + p->has_vi = 1; + vi = p->vi.bit_rate; + } + } + break; + + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + if (!p->has_ai){ + if(get_ainfo(p->buf, p->count, &p->ai,1) >=0) { + p->has_ai = 1; + ai = p->ai.bit_rate; + } + } + break; + } + + if (p->has_vi && vi && !muxr){ + muxr = (vi+ai)/400; + } + + if ( start && muxr && (p->buf[7] & PTS_ONLY) && (p->has_ai || + p->buf[9+p->buf[8]+4] == 0xb3)){ + SCR = trans_pts_dts(p->pts)-3600; + + check = write_ps_header(pbuf, + SCR, + muxr, 1, 0, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0); + + p->func(pbuf, check , p->data); + } + + if (muxr && !start && vi){ + SCR = trans_pts_dts(p->pts)-3600; + check = write_ps_header(pbuf, + SCR, + muxr, 1, 0, 0, 1, 1, 1, + 0xC0, 0, 64, 0xE0, 1, 460); + start = 1; + p->func(pbuf, check , p->data); + } + + if (start) + p->func(p->buf, p->count, p->data); + } +} + +void send_ipack(ipack *p) +{ + int streamid=0; + int off; + int ac3_off = 0; + AudioInfo ai; + int nframes= 0; + int f=0; + + if (p->count < 10) return; + p->buf[3] = p->cid; + p->buf[4] = (uint8_t)(((p->count-6) & 0xFF00) >> 8); + p->buf[5] = (uint8_t)((p->count-6) & 0x00FF); + + + if (p->cid == PRIVATE_STREAM1){ + + off = 9+p->buf[8]; + streamid = p->buf[off]; + if ((streamid & 0xF8) == 0x80){ + ai.off = 0; + ac3_off = ((p->buf[off+2] << 8)| p->buf[off+3]); + if (ac3_off < p->count) + f=get_ac3info(p->buf+off+3+ac3_off, + p->count-ac3_off, &ai,0); + if ( !f ){ + nframes = (p->count-off-3-ac3_off)/ + ai.framesize + 1; + p->buf[off+1] = nframes; + p->buf[off+2] = (ac3_off >> 8)& 0xFF; + p->buf[off+3] = (ac3_off)& 0xFF; + + ac3_off += nframes * ai.framesize - p->count; + } + } + } + + if (p->ps) ps_pes(p); + else p->func(p->buf, p->count, p->data); + + switch ( p->mpeg ){ + case 2: + + p->buf[6] = 0x80; + p->buf[7] = 0x00; + p->buf[8] = 0x00; + p->count = 9; + + if (p->cid == PRIVATE_STREAM1 && (streamid & 0xF8)==0x80 ){ + p->count += 4; + p->buf[9] = streamid; + p->buf[10] = 0; + p->buf[11] = (ac3_off >> 8)& 0xFF; + p->buf[12] = (ac3_off)& 0xFF; + } + + break; + case 1: + p->buf[6] = 0x0F; + p->count = 7; + break; + } + +} + + +static void write_ipack(ipack *p, uint8_t *data, int count) +{ + AudioInfo ai; + uint8_t headr[3] = { 0x00, 0x00, 0x01} ; + int diff =0; + + if (p->count < 6){ + if (trans_pts_dts(p->pts) > trans_pts_dts(p->last_pts)) + memcpy(p->last_pts, p->pts, 5); + p->count = 0; + memcpy(p->buf+p->count, headr, 3); + p->count += 6; + } + if ( p->size == p->size_orig && p->plength && + (diff = 6+p->plength - p->found + p->count +count) > p->size && + diff < 3*p->size/2){ + + p->size = diff/2; +// fprintf(stderr,"size: %d \n",p->size); + } + + if (p->cid == PRIVATE_STREAM1 && p->count == p->hlength+9){ + if ((data[0] & 0xF8) != 0x80){ + int ac3_off; + + ac3_off = get_ac3info(data, count, &ai,0); + if (ac3_off>=0 && ai.framesize){ + p->buf[p->count] = 0x80; + p->buf[p->count+1] = (p->size - p->count + - 4 - ac3_off)/ + ai.framesize + 1; + p->buf[p->count+2] = (ac3_off >> 8)& 0xFF; + p->buf[p->count+3] = (ac3_off)& 0xFF; + p->count+=4; + + } + } + } + + if (p->count + count < p->size){ + memcpy(p->buf+p->count, data, count); + p->count += count; + } else { + int rest = p->size - p->count; + if (rest < 0) rest = 0; + memcpy(p->buf+p->count, data, rest); + p->count += rest; +// fprintf(stderr,"count: %d \n",p->count); + send_ipack(p); + if (count - rest > 0) + write_ipack(p, data+rest, count-rest); + } +} + +void instant_repack (uint8_t *buf, int count, ipack *p) +{ + + int l; + unsigned short *pl; + int c=0; + + while (c < count && (p->mpeg == 0 || + (p->mpeg == 1 && p->found < 7) || + (p->mpeg == 2 && p->found < 9)) + && (p->found < 5 || !p->done)){ + switch ( p->found ){ + case 0: + case 1: + if (buf[c] == 0x00) p->found++; + else p->found = 0; + c++; + break; + case 2: + if (buf[c] == 0x01) p->found++; + else if (buf[c] == 0){ + p->found = 2; + } else p->found = 0; + c++; + break; + case 3: + p->cid = 0; + switch (buf[c]){ + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + p->done = 1; + case PRIVATE_STREAM1: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + p->found++; + p->cid = buf[c]; + c++; + break; + default: + p->found = 0; + break; + } + break; + + + case 4: + if (count-c > 1){ + pl = (unsigned short *) (buf+c); + p->plength = ntohs(*pl); + p->plen[0] = buf[c]; + c++; + p->plen[1] = buf[c]; + c++; + p->found+=2; + } else { + p->plen[0] = buf[c]; + p->found++; + return; + } + break; + case 5: + p->plen[1] = buf[c]; + c++; + pl = (unsigned short *) p->plen; + p->plength = ntohs(*pl); + p->found++; + break; + + + case 6: + if (!p->done){ + p->flag1 = buf[c]; + c++; + p->found++; + if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2; + else { + p->hlength = 0; + p->which = 0; + p->mpeg = 1; + p->flag2 = 0; + } + } + break; + + case 7: + if ( !p->done && p->mpeg == 2){ + p->flag2 = buf[c]; + c++; + p->found++; + } + break; + + case 8: + if ( !p->done && p->mpeg == 2){ + p->hlength = buf[c]; + c++; + p->found++; + } + break; + + default: + + break; + } + } + + + if (c == count) return; + + if (!p->plength) p->plength = MMAX_PLENGTH-6; + + + if ( p->done || ((p->mpeg == 2 && p->found >= 9) || + (p->mpeg == 1 && p->found >= 7)) ){ + switch (p->cid){ + + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case PRIVATE_STREAM1: + + if (p->mpeg == 2 && p->found == 9){ + write_ipack(p, &p->flag1, 1); + write_ipack(p, &p->flag2, 1); + write_ipack(p, &p->hlength, 1); + } + + if (p->mpeg == 1 && p->found == 7){ + write_ipack(p, &p->flag1, 1); + } + + + if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) && + p->found < 14){ + while (c < count && p->found < 14){ + p->pts[p->found-9] = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + } + if (c == count) return; + } + + if (p->mpeg == 1 && p->which < 2000){ + + if (p->found == 7) { + p->check = p->flag1; + p->hlength = 1; + } + + while (!p->which && c < count && + p->check == 0xFF){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + } + + if ( c == count) return; + + if ( (p->check & 0xC0) == 0x40 && !p->which){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + + p->which = 1; + if ( c == count) return; + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return; + } + + if (p->which == 1){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return; + } + + if ( (p->check & 0x30) && p->check != 0xFF){ + p->flag2 = (p->check & 0xF0) << 2; + p->pts[0] = p->check; + p->which = 3; + } + + if ( c == count) return; + if (p->which > 2){ + if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_ONLY){ + while (c < count && + p->which < 7){ + p->pts[p->which-2] = + buf[c]; + write_ipack(p,buf+c,1); + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return; + } else if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_DTS){ + while (c < count && + p->which< 12){ + if (p->which< 7) + p->pts[p->which + -2] = + buf[c]; + write_ipack(p,buf+c,1); + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return; + } + p->which = 2000; + } + + } + + while (c < count && p->found < p->plength+6){ + l = count -c; + if (l+p->found > p->plength+6) + l = p->plength+6-p->found; + write_ipack(p, buf+c, l); + p->found += l; + c += l; + } + + break; + } + + + if ( p->done ){ + if( p->found + count - c < p->plength+6){ + p->found += count-c; + c = count; + } else { + c += p->plength+6 - p->found; + p->found = p->plength+6; + } + } + + if (p->plength && p->found == p->plength+6) { + send_ipack(p); + reset_ipack(p); + if (c < count) + instant_repack(buf+c, count-c, p); + } + } + return; +} + +void write_out_es(uint8_t *buf, int count,void *priv) +{ + ipack *p = (ipack *) priv; + uint8_t payl = buf[8]+9+p->start-1; + + write(p->fd, buf+payl, count-payl); + p->start = 1; +} + +void write_out_pes(uint8_t *buf, int count,void *priv) +{ + ipack *p = (ipack *) priv; + write(p->fd, buf, count); +} + + + +int64_t ts_demux(int fdin, int fdv_out,int fda_out,uint16_t pida, + uint16_t pidv, int es) +{ + uint8_t buf[IN_SIZE]; + uint8_t mbuf[TS_SIZE]; + int i; + int count = 1; + uint16_t pid; + ipack pa, pv; + ipack *p; + uint8_t *sb; + int64_t apts=0; + int64_t vpts=0; + int verb = 0; + uint64_t length =0; + uint64_t l=0; + int perc =0; + int last_perc =0; + + if (fdin != STDIN_FILENO) verb = 1; + + if (verb) { + length = lseek(fdin, 0, SEEK_END); + lseek(fdin,0,SEEK_SET); + } + + if (!pida || !pidv) + find_avpids(fdin, &pidv, &pida); + + if (es){ + init_ipack(&pa, IPACKS,write_out_es, 0); + init_ipack(&pv, IPACKS,write_out_es, 0); + } else { + init_ipack(&pa, IPACKS,write_out_pes, 0); + init_ipack(&pv, IPACKS,write_out_pes, 0); + } + pa.fd = fda_out; + pv.fd = fdv_out; + pa.data = (void *)&pa; + pv.data = (void *)&pv; + + count = save_read(fdin,mbuf,TS_SIZE); + if (count) l+=count; + for ( i = 0; i < 188 ; i++){ + if ( mbuf[i] == 0x47 ) break; + } + if ( i == 188){ + fprintf(stderr,"Not a TS\n"); + return 0; + } else { + memcpy(buf,mbuf+i,TS_SIZE-i); + count = save_read(fdin,mbuf,i); + if (count) l+=count; + memcpy(buf+TS_SIZE-i,mbuf,i); + i = 188; + } + + count = 1; + while (count > 0){ + count = save_read(fdin,buf+i,IN_SIZE-i)+i; + if (count) l+=count; + if (verb && perc >last_perc){ + perc = (100*l)/length; + fprintf(stderr,"Reading TS %d %%\r",perc); + last_perc = perc; + } + + for( i = 0; i < count; i+= TS_SIZE){ + uint8_t off = 0; + + if ( count - i < TS_SIZE) break; + + pid = get_pid(buf+i+1); + if (!(buf[3+i]&0x10)) // no payload? + continue; + if ( buf[1+i]&0x80){ + fprintf(stderr,"Error in TS for PID: %d\n", + pid); + } + if (pid == pidv){ + p = &pv; + } else { + if (pid == pida){ + p = &pa; + } else continue; + } + + if ( buf[3+i] & 0x20) { // adaptation field? + off = buf[4+i] + 1; + } + + if ( buf[1+i]&0x40) { + if (p->plength == MMAX_PLENGTH-6){ + p->plength = p->found-6; + p->found = 0; + send_ipack(p); + reset_ipack(p); + } + sb = buf+4+off+i; + if( es && + !p->start && (sb[7] & PTS_DTS_FLAGS)){ + uint8_t *pay = sb+sb[8]+9; + int l = TS_SIZE - 13 - off - sb[8]; + if ( pid == pidv && + (p->start = + get_vinfo( pay, l,&p->vi,1)+1) >0 + ){ + vpts = trans_pts_dts(sb+9); + printf("vpts : %fs\n", + vpts/90000.); + } + if ( pid == pida && es==1 && + (p->start = + get_ainfo( pay, l,&p->ai,1)+1) >0 + ){ + apts = trans_pts_dts(sb+9); + printf("apts : %fs\n", + apts/90000.); + } + if ( pid == pida && es==2 && + (p->start = + get_ac3info( pay, l,&p->ai,1)+1) >0 + ){ + apts = trans_pts_dts(sb+9); + printf("apts : %fs\n", + apts/90000.); + } + } + } + + if (p->start) + instant_repack(buf+4+off+i, TS_SIZE-4-off, p); + } + i = 0; + + } + + return (vpts-apts); +} + +void ts2es_opt(int fdin, uint16_t pidv, ipack *p, int verb) +{ + uint8_t buf[IN_SIZE]; + uint8_t mbuf[TS_SIZE]; + int i; + int count = 1; + uint64_t length =0; + uint64_t l=0; + int perc =0; + int last_perc =0; + uint16_t pid; + + if (verb) { + length = lseek(fdin, 0, SEEK_END); + lseek(fdin,0,SEEK_SET); + } + + count = save_read(fdin,mbuf,TS_SIZE); + if (count) l+=count; + for ( i = 0; i < 188 ; i++){ + if ( mbuf[i] == 0x47 ) break; + } + if ( i == 188){ + fprintf(stderr,"Not a TS\n"); + return; + } else { + memcpy(buf,mbuf+i,TS_SIZE-i); + count = save_read(fdin,mbuf,i); + if (count) l+=count; + memcpy(buf+TS_SIZE-i,mbuf,i); + i = 188; + } + + count = 1; + while (count > 0){ + count = save_read(fdin,buf+i,IN_SIZE-i)+i; + if (count) l+=count; + if (verb && perc >last_perc){ + perc = (100*l)/length; + fprintf(stderr,"Reading TS %d %%\r",perc); + last_perc = perc; + } + + for( i = 0; i < count; i+= TS_SIZE){ + uint8_t off = 0; + + if ( count - i < TS_SIZE) break; + + pid = get_pid(buf+i+1); + if (!(buf[3+i]&0x10)) // no payload? + continue; + if ( buf[1+i]&0x80){ + fprintf(stderr,"Error in TS for PID: %d\n", + pid); + } + if (pid != pidv){ + continue; + } + + if ( buf[3+i] & 0x20) { // adaptation field? + off = buf[4+i] + 1; + } + + if ( buf[1+i]&0x40) { + if (p->plength == MMAX_PLENGTH-6){ + p->plength = p->found-6; + p->found = 0; + send_ipack(p); + reset_ipack(p); + } + } + + instant_repack(buf+4+off+i, TS_SIZE-4-off, p); + } + i = 0; + + } +} + +void ts2es(int fdin, uint16_t pidv) +{ + ipack p; + int verb = 0; + + init_ipack(&p, IPACKS,write_out_es, 0); + p.fd = STDOUT_FILENO; + p.data = (void *)&p; + + if (fdin != STDIN_FILENO) verb = 1; + + ts2es_opt(fdin, pidv, &p, verb); +} + + +void change_aspect(int fdin, int fdout, int aspect) +{ + ps_packet ps; + pes_packet pes; + int neof,i; + + do { + init_ps(&ps); + neof = read_ps(fdin,&ps); + write_ps(fdout,&ps); + for (i = 0; i < ps.npes; i++){ + uint8_t *buf; + int c = 0; + int l; + + init_pes(&pes); + read_pes(fdin, &pes); + + buf = pes.pes_pckt_data; + + switch (pes.stream_id){ + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + l=pes.length; + break; + default: + l = 0; + break; + } + while ( c < l - 6){ + if (buf[c] == 0x00 && + buf[c+1] == 0x00 && + buf[c+2] == 0x01 && + buf[c+3] == 0xB3) { + c += 4; + buf[c+3] &= 0x0f; + buf[c+3] |= aspect; + } + else c++; + } + write_pes(fdout,&pes); + } + } while( neof > 0 ); +} diff --git a/plugins/streamdev/streamdev-cvs/libdvbmpeg/transform.h b/plugins/streamdev/streamdev-cvs/libdvbmpeg/transform.h new file mode 100644 index 0000000..c65fa0c --- /dev/null +++ b/plugins/streamdev/streamdev-cvs/libdvbmpeg/transform.h @@ -0,0 +1,250 @@ +/* + * dvb-mpegtools for the Siemens Fujitsu DVB PCI card + * + * Copyright (C) 2000, 2001 Marcus Metzler + * for convergence integrated media GmbH + * Copyright (C) 2002 Marcus Metzler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + + * The author can be reached at mocm@metzlerbros.de, + + */ + +#ifndef _TS_TRANSFORM_H_ +#define _TS_TRANSFORM_H_ + +#include +#include +#include +#include +#include "remux.h" + +#define PROG_STREAM_MAP 0xBC +#ifndef PRIVATE_STREAM1 +#define PRIVATE_STREAM1 0xBD +#endif +#define PADDING_STREAM 0xBE +#ifndef PRIVATE_STREAM2 +#define PRIVATE_STREAM2 0xBF +#endif +#define AUDIO_STREAM_S 0xC0 +#define AUDIO_STREAM_E 0xDF +#define VIDEO_STREAM_S 0xE0 +#define VIDEO_STREAM_E 0xEF +#define ECM_STREAM 0xF0 +#define EMM_STREAM 0xF1 +#define DSM_CC_STREAM 0xF2 +#define ISO13522_STREAM 0xF3 +#define PROG_STREAM_DIR 0xFF + +#define BUFFYSIZE 10*MAX_PLENGTH +#define MAX_PTS 8192 +#define MAX_FRAME 8192 +#define MAX_PACK_L 4096 +#define PS_HEADER_L1 14 +#define PS_HEADER_L2 (PS_HEADER_L1+18) +#define MAX_H_SIZE (PES_H_MIN + PS_HEADER_L1 + 5) +#define PES_MIN 7 +#define PES_H_MIN 9 + +//flags2 +#define PTS_DTS_FLAGS 0xC0 +#define ESCR_FLAG 0x20 +#define ES_RATE_FLAG 0x10 +#define DSM_TRICK_FLAG 0x08 +#define ADD_CPY_FLAG 0x04 +#define PES_CRC_FLAG 0x02 +#define PES_EXT_FLAG 0x01 + +//pts_dts flags +#define PTS_ONLY 0x80 +#define PTS_DTS 0xC0 + +#define TS_SIZE 188 +#define TRANS_ERROR 0x80 +#define PAY_START 0x40 +#define TRANS_PRIO 0x20 +#define PID_MASK_HI 0x1F +//flags +#define TRANS_SCRMBL1 0x80 +#define TRANS_SCRMBL2 0x40 +#define ADAPT_FIELD 0x20 +#define PAYLOAD 0x10 +#define COUNT_MASK 0x0F + +// adaptation flags +#define DISCON_IND 0x80 +#define RAND_ACC_IND 0x40 +#define ES_PRI_IND 0x20 +#define PCR_FLAG 0x10 +#define OPCR_FLAG 0x08 +#define SPLICE_FLAG 0x04 +#define TRANS_PRIV 0x02 +#define ADAP_EXT_FLAG 0x01 + +// adaptation extension flags +#define LTW_FLAG 0x80 +#define PIECE_RATE 0x40 +#define SEAM_SPLICE 0x20 + + +#define MAX_PLENGTH 0xFFFF +#define MMAX_PLENGTH (64*MAX_PLENGTH) + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define P2P_LENGTH 2048 + + enum{NOPES, AUDIO, VIDEO, AC3}; + + typedef struct p2pstruct { + int found; + uint8_t buf[MMAX_PLENGTH]; + uint8_t cid; + uint8_t subid; + uint32_t plength; + uint8_t plen[2]; + uint8_t flag1; + uint8_t flag2; + uint8_t hlength; + uint8_t pts[5]; + int mpeg; + uint8_t check; + int fd1; + int fd2; + int es; + int filter; + int which; + int done; + int repack; + uint16_t bigend_repack; + void (*func)(uint8_t *buf, int count, void *p); + int startv; + int starta; + int64_t apts; + int64_t vpts; + uint16_t pid; + uint16_t pida; + uint16_t pidv; + uint8_t acounter; + uint8_t vcounter; + uint8_t count0; + uint8_t count1; + void *data; + } p2p; + + + uint64_t trans_pts_dts(uint8_t *pts); + int write_ts_header(uint16_t pid, uint8_t *counter, int pes_start, + uint8_t *buf, uint8_t length); + uint16_t get_pid(uint8_t *pid); + void init_p2p(p2p *p, void (*func)(uint8_t *buf, int count, void *p), + int repack); + void get_pes (uint8_t *buf, int count, p2p *p, void (*func)(p2p *p)); + void get_pes (uint8_t *buf, int count, p2p *p, void (*func)(p2p *p)); + void pes_repack(p2p *p); + void setup_pes2ts( p2p *p, uint32_t pida, uint32_t pidv, + void (*ts_write)(uint8_t *buf, int count, void *p)); + void kpes_to_ts( p2p *p,uint8_t *buf ,int count ); + void setup_ts2pes( p2p *pa, p2p *pv, uint32_t pida, uint32_t pidv, + void (*pes_write)(uint8_t *buf, int count, void *p)); + void kts_to_pes( p2p *p, uint8_t *buf); + void pes_repack(p2p *p); + void extract_from_pes(int fdin, int fdout, uint8_t id, int es); + int64_t pes_dmx(int fdin, int fdouta, int fdoutv, int es); + void pes_to_ts2( int fdin, int fdout, uint16_t pida, uint16_t pidv); + void ts_to_pes( int fdin, uint16_t pida, uint16_t pidv, int pad); + int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr); + int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr); + int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr); + void filter_audio_from_pes(int fdin, int fdout, uint8_t id, + uint8_t subid); + + +//instant repack + + typedef struct ipack_s { + int size; + int size_orig; + int found; + int ps; + int has_ai; + int has_vi; + AudioInfo ai; + VideoInfo vi; + uint8_t *buf; + uint8_t cid; + uint32_t plength; + uint8_t plen[2]; + uint8_t flag1; + uint8_t flag2; + uint8_t hlength; + uint8_t pts[5]; + uint8_t last_pts[5]; + int mpeg; + uint8_t check; + int which; + int done; + void *data; + void *data2; + void (*func)(uint8_t *buf, int size, void *priv); + int count; + int start; + int fd; + int fd1; + int fd2; + int ffd; + int playing; + } ipack; + + void instant_repack (uint8_t *buf, int count, ipack *p); + void init_ipack(ipack *p, int size, + void (*func)(uint8_t *buf, int size, void *priv), + int pad); + void free_ipack(ipack * p); + void send_ipack(ipack *p); + void reset_ipack(ipack *p); + void ps_pes(ipack *p); + // use with ipack structure, repack size and callback func + + int64_t ts_demux(int fd_in, int fdv_out,int fda_out,uint16_t pida, + uint16_t pidv, int es); + + void ts2es(int fdin, uint16_t pidv); + void ts2es_opt(int fdin, uint16_t pidv, ipack *p, int verb); + void insert_pat_pmt( int fdin, int fdout); + void change_aspect(int fdin, int fdout, int aspect); + +// SV: all made non-static: + void pes_in_ts(p2p *p); + +// SV: moved from .c file: +#define IPACKS 2048 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _TS_TRANSFORM_H_*/ + + + -- cgit v1.2.3