Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-dvb] Sound, live AC3, timings and reinsert into DVB (AV711x)



Hi,

    during the time with playing around with AC3 routing from the DVB
card over VDR to the S/P-DIF out of a sound chip, I've discovered
a problem with the most sound cards.

Most sound cards (beside high expensive) have an own quart
as reference clock on board and NO slave mode for getting
an external reference clock over an internal S/P-DIF connector.
This leads to the problem if the `48kHz' rate of reading out AC3 from
the DVB card isn't exactly the same as the `48kHz' of the sound
chip, in other words under or overruns will occur.
(For the case of an underrun it is possible to send some LPCM warped
 AC3 frames twice to avoid the underrun, this works for _my_ A/V receiver.
 For the other case an overrun I see no way to avoid this.
 In the first case I'm using a hacked vdr 1.0.2 + AIO which has
 an own thread for reading out and warping AC3 into LPCM to get it
 onto the sound card via ALSA).

The only way really to avoid such under/overruns is to use the
S/P-DIF out of the DVB card.  Therefore I've done a look on the
old DVB driver I'm using (no newhead) and found out that it may possible
to use in dvb_filter.c the same technique as I use with VDR to
warp AC3 into LPCM and and redirect the result to the DVB card
(which is done e.g. in the DVD patch of Andreas Schultz).

The problem is: the DVB drivers start/stop/usage of the callback for
filtering out a pid of the private stream 1 used for AC3 has to
be put into instant_repack().  How this could be done?

At the end I've put an example code howto warping AC3 into LPCM with
dvb_filter.c/dvb_filter.h.  New files are warp2pcm.h which does the
main work and dvb_main.c which can be compiled for usage in user space

      gcc -O2 -o dvb_main dvb_main.c

After that an existing vdr mpeg can be converted

      mv 001.vdr 001.vdr.bak
      ./dvb_main < 001.vdr.bak > 001.vdr

for testing. Maybe the new 001.vdr needs to be handled with
genindex to get index.vdr uptodate.

It _seems_ that the usage of the start sequence

    0xA0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x81

for getting the AV711x into the linear PCM mode also helps to
set none audio mode for the S/P-DIF out of the DVB card (1.3).
(I've done some experiments with the sequence found in 
 apps/tuxzap/src/dvb_formats.c).
Nevertheless, the AC3 frames has to put into 1536 PCM samples
padded with zeros, to fulfill 32ms duration at 48kHz.


     Comments?

           Werner

========================================================================
--- dvb_main.c
+++ dvb_main.c	Thu Dec 12 14:43:10 2002
@@ -0,0 +1,28 @@
+#define USER_SPACE
+#include "dvb_filter.h"
+#include "dvb_filter.c"
+
+#define IPACKS 2048
+static void
+play_cb(u8 *buf, int count, void *priv)
+{
+	fwrite(buf, sizeof(u8), count, stdout);
+}
+
+int main(int argc, char *argv[])
+{
+	struct ipack_s ipack;
+	u8 buf[2048];
+	size_t len;
+
+	init_ipack(&ipack, IPACKS, play_cb);
+	enable2pcm(&ipack);
+
+	while((len = fread(&buf[0], sizeof(u8), sizeof(buf), stdin))) {
+		instant_repack(buf, len, &ipack);
+	}
+	disable2pcm(&ipack);
+	reset_ipack(&ipack);
+	free_ipack(&ipack);
+	return 0;
+}
--- warp2pcm.h
+++ warp2pcm.h	Fri Nov 29 13:35:27 2002
@@ -0,0 +1,269 @@
+#ifndef _WARP_2_PCM_
+#define _WARP_2_PCM_
+
+# define USE_MAXIPACK
+# ifndef USE_MAXIPACK
+# else
+# endif
+//# define DSM_TRICK
+# define USE_EXTENSION_STD
+
+typedef struct _pcm_s {
+	uint8_t *magic;
+	uint8_t *tail;
+	int msize;
+	int count;
+} pcm_t;
+
+static inline void framecpy(uint8_t *pts, pcm_t pcm,
+			    void (*fcpy)(u8*, int), AudioInfo ai, u32 payload)
+{
+	uint8_t start[9] = { 0x00, 0x00, 0x01, PRIVATE_STREAM1, };
+	uint8_t lpcmh[7] = {aLPCM, 0xff, 0x00, 0x00, 0x00, 0x00, 0x81};
+	static const uint8_t zero[2048];
+	int has_pts = (pts[1] != 0);
+	int fsize = 0;
+
+	fsize += sizeof(start);
+	fsize += sizeof(lpcmh);
+	fsize += pts[1];
+	fsize += pcm.msize;
+	fsize += ai.framesize;
+
+	if (fsize < sizeof(zero))
+		fsize = sizeof(zero);
+	if (fsize > sizeof(zero))
+		fsize = 2*sizeof(zero);
+
+	switch (ai.frequency) {
+	case 32000:
+		lpcmh[5] = 0x31;
+		break;
+	case 44100:
+		lpcmh[5] = 0x21;
+		break;
+	default:
+	case 48000:
+		lpcmh[5] = 0x01;
+		break;
+	}
+
+	start[6] = 0x80;		/* Most 0x80 or 0x81 if copy bit is set */
+	start[7] = pts[0];		/* PTS flags */
+	start[8] = pts[1];		/* PTS field length */
+
+	while (pcm.count > 0) {
+		int lenght = fsize;
+		int size = lenght - sizeof(lpcmh);
+
+		if (has_pts)
+			size -= start[8];	/* pts[1] and maybe more */
+
+		if (pcm.count < size) {
+			lenght -= (size - pcm.count);
+			size = pcm.count;
+		}
+
+		lenght -= 6;
+		start[4] = (lenght >> 8) & 0xff;
+		start[5] = (lenght) & 0xff;
+
+		/*
+		 * Start this frame
+		 */
+		fcpy(start, sizeof(start));
+
+		/*
+		 * PTS follows if any
+		 */
+		if (has_pts)
+			fcpy(&pts[2], pts[1]);
+
+		/*
+		 * Payload follows: first the linear PCM switch
+		 */
+		fcpy(lpcmh, sizeof(lpcmh));
+
+		/*
+		 * Here the data will be mapped into 1536 audio samples
+		 * (6144 bytes for 16 bit stereo) and zero padded.
+		 */
+		if (payload) {
+			if (pcm.count == 6144) {
+				fcpy(pcm.magic, pcm.msize);
+				pcm.count -= pcm.msize;
+				size -= pcm.msize;
+			}
+			if (payload <= size) {
+				fcpy(pcm.tail, payload);
+				pcm.tail  += payload;
+				pcm.count -= payload;
+				size -= payload;
+				payload = 0;
+			} else {
+				fcpy(pcm.tail, size);
+				pcm.tail  += size;
+				pcm.count -= size;
+				payload -= size;
+				size = 0;
+			}
+		}
+
+		/*
+		 * Fillup the rest with zeros
+		 */
+		if (size) {
+			while (size > sizeof(zero)) {
+				fcpy((u8*)zero, sizeof(zero));
+				pcm.count -= sizeof(zero);
+				size -= sizeof(zero);
+			}
+			fcpy((u8*)zero, size);
+			pcm.count -= size;
+			size = 0;
+		}
+
+		/*
+		 * Clear PTS for follow ups
+		 */
+		has_pts = 0;
+		start[7] = 0x00;
+		start[8] = 0x00;
+	}
+}
+
+static inline void init2pcm(uint8_t *pts, ipack *p, AudioInfo ai);
+
+static inline void warp2pcm(ipack *p, int offset, AudioInfo ai)
+{
+	pcm_t pcm;
+	uint8_t magic[8] = { 0xf8, 0x72, 0x4e, 0x1f, };
+	void fcpy (u8* data, int size) {
+		p->func(data, size, p->data);
+	};
+
+	pcm.magic = &magic[0];
+	pcm.msize = sizeof(magic);
+	pcm.tail  = &(p->buf[offset]);
+	pcm.count = 6144;		/* size of 32ms PCM buffer at 48kHz */
+
+	magic[4] = ai.bsmod;		/* bsmod */
+	magic[5] = 0x01;		/* None audio PCM */
+	magic[6] = ((ai.framesize*8) >> 8) & 0xff;
+	magic[7] = ((ai.framesize*8) & 0xff);
+
+	if (p->init_subids > 0)
+		init2pcm(&(p->buf[7]), p, ai);
+	else
+		framecpy(&(p->buf[7]), pcm, fcpy, ai, ai.framesize);
+}
+
+static inline void init2pcm(uint8_t *pts, ipack *p, const AudioInfo ai)
+{
+	pcm_t pcm;
+	uint8_t magic[8] = { 0xf8, 0x72, 0x4e, 0x1f, };
+# if defined(DSM_TRICK) || defined(USE_EXTENSION_STD)
+	int off = pts[1];
+	uint8_t ext_pts[2+off+4];
+# endif
+	void fcpy (u8* data, int size) {
+		p->func(data, size, p->data);
+	};
+
+	(void)memcpy(&(ext_pts[0]), pts, 2+off);
+
+# ifdef DSM_TRICK
+	ext_pts[0] |= 0x08;		/* DSM trick_mode_flag */
+	ext_pts[1]++;
+	ext_pts[2+off] = 0xE0; off++;	/* Reserved DSM trick mode */
+# endif
+# ifdef USE_EXTENSION_STD
+	ext_pts[0] |= 0x01;		/* Set PES extension flag */
+	ext_pts[1] += 3;
+	ext_pts[2+off] = 0x10; off++;	/* P-STD buffer flag (fourth bit) */
+#  if 1
+	ext_pts[2+off] = 0x40; off++;	/* P-STD buffer scale factor is 0 */
+	ext_pts[2+off] = 0x32; off++;	/* P-STD buffer size is 50*128 = 6400 byte */
+#  else
+	ext_pts[2+off] = 0x60; off++;	/* P-STD buffer scale factor is 1 */
+	ext_pts[2+off] = 0x06; off++;	/* P-STD buffer size is 6*1024 = 6144 byte */
+#  endif
+# endif
+
+	pcm.magic = &magic[0];
+	pcm.msize = sizeof(magic);
+	pcm.tail  = NULL;
+	pcm.count = 6144;
+
+	if (p->init_subids > 1) {
+		magic[4] = 7<<5;	/* null frame requires stream = 7 */
+		magic[5] = 0x00;	/* Null data_type */
+		magic[6] = 0x00;
+		magic[7] = 0x00;
+	} else {
+		magic[4] = 0x00;	/* Audio ES Channel empty */
+		magic[5] = 0x03;	/* wait for DD Decoder or pause */
+		magic[6] = 0x00;
+		magic[7] = 0x40;
+	}
+
+	framecpy(ext_pts, pcm, fcpy, ai, 0);
+
+	if (p->init_subids > 0)
+		p->init_subids--;
+}
+
+static inline void end2pcm(ipack *p)
+{
+	pcm_t pcm;
+	uint8_t magic[8] = { 0xf8, 0x72, 0x4e, 0x1f, };
+	uint8_t pts[10] = {0x00, 0x00, };
+	AudioInfo ai;
+# if defined(DSM_TRICK) || defined(USE_EXTENSION_STD)
+	int off = 0;
+# endif
+	void fcpy (u8* data, int size) {
+		p->func(data, size, p->data);
+	};
+
+# ifdef USE_EXTENSION_STD
+	pts[0] |= 0x01;			/* Set PES extension flag */
+	pts[1] += 3;
+	pts[2+off] = 0x10; off++;	/* P-STD buffer flag (fourth bit) */
+	pts[2+off] = 0x40; off++;	/* P-STD buffer scale factor is 0 */
+	pts[2+off] = 0x10; off++;	/* P-STD buffer size is 16*128 = 2048 byte */
+# endif
+
+	pcm.magic = &magic[0];
+	pcm.msize = sizeof(magic);
+	pcm.tail  = NULL;
+	pcm.count = 6144;
+	ai.framesize = 0;
+	ai.frequency = 0;
+
+	magic[4] = 0x01;		/* User stop, skip or error */
+	magic[5] = 0x03;		/* wait for DD Decoder or pause */
+	magic[6] = 0x00;
+	magic[7] = 0x40;
+
+	framecpy(pts, pcm, fcpy, ai, 0);
+
+	p->init_subids = 0;
+}
+
+void enable2pcm(ipack *p)
+{
+	if (!p->repack_subids) {
+		p->repack_subids = 1;
+		p->init_subids = 10;
+	}
+}
+
+void disable2pcm(ipack *p)
+{
+	if (p->repack_subids) {
+		p->repack_subids = 0;
+		p->init_subids = -1;
+	}
+}
+#endif /* _WARP_2_PCM_ */
--- dvb_filter.c
+++ dvb_filter.c	Thu Dec 12 14:42:44 2002
@@ -0,0 +1,800 @@
+#ifndef USER_SPACE
+#include <linux/module.h>
+#include <linux/videodev.h>
+#endif
+#include "dvb_filter.h"
+
+#ifndef USER_SPACE
+#ifdef MODULE
+MODULE_DESCRIPTION("");
+MODULE_AUTHOR("Marcus Metzler, Ralph Metzler");
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+#endif
+#endif
+
+#ifndef EXPORT_INFO
+static int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai);
+#endif
+
+#ifdef DEBUG_FILTER
+# define dprintk(args...)	printk(KERN_DEBUG ##args);
+#else
+# define dprintk(args...)
+#endif
+
+#include "warp2pcm.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};
+
+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}}; 
+
+
+
+void pes2ts_init(pes2ts_t *p2ts, unsigned short pid, 
+		 pes2ts_cb_t *cb, void *priv)
+{
+	unsigned char *buf=p2ts->buf;
+
+	buf[0]=0x47;
+	buf[1]=(pid>>8);
+	buf[2]=pid&0xff;
+	p2ts->cc=0;
+	p2ts->cb=cb;
+	p2ts->priv=priv;
+}
+
+int pes2ts(pes2ts_t *p2ts, unsigned char *pes, int len)
+{
+	unsigned char *buf=p2ts->buf;
+	int ret=0, rest;
+	
+	//len=6+((pes[4]<<8)|pes[5]);
+
+	buf[1]|=0x40;
+	while (len>=184) {
+		buf[3]=0x10|((p2ts->cc++)&0x0f);
+		memcpy(buf+4, pes, 184);
+		if ((ret=p2ts->cb(p2ts->priv, buf)))
+			return ret;
+		len-=184; pes+=184;
+		buf[1]&=~0x40;
+	}
+	if (!len)
+	        return 0;
+	buf[3]=0x30|((p2ts->cc++)&0x0f);
+	rest=183-len;
+	if (rest) {
+	        buf[5]=0x00;
+		if (rest-1)
+			memset(buf+6, 0xff, rest-1);
+	}
+	buf[4]=rest;
+	memcpy(buf+5+rest, pes, len);
+	return p2ts->cb(p2ts->priv, buf);
+}
+
+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;
+	if (!p->repack_subids && p->init_subids < 0)
+		end2pcm(p);
+}
+
+void init_ipack(ipack *p, int size,
+		void (*func)(u8 *buf, int size, void *priv))
+{
+	if ( !(p->buf = vmalloc(size*sizeof(u8))) ){
+		printk ("Couldn't allocate memory for ipack\n");
+	}
+	p->size = size;
+	p->func = func;
+	p->repack_subids = 0;
+	p->init_subids = 0;
+	reset_ipack(p);
+}
+
+void free_ipack(ipack * p)
+{
+	if (p->buf) vfree(p->buf);
+}
+
+void send_ipack(ipack *p)
+{
+	int off = 0;
+	AudioInfo ai;
+	int ac3_off = 0;
+	int streamid= 0;
+
+	switch ( p->mpeg ){
+	case 2:		
+		if (p->count < 10) return;
+		p->buf[3] = p->cid;
+
+		ai.off = ai.framesize = 0;
+		p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8);
+		p->buf[5] = (u8)((p->count-6) & 0x00FF);
+		if (p->repack_subids && p->cid == PRIVATE_STREAM1) {
+			off = 9+p->buf[8];
+			streamid = p->buf[off];
+
+			if (p->buf[off] == 0x0B && p->buf[off+1] == 0x77) {
+
+				get_ac3info(&p->buf[off], p->count - off, &ai);
+
+			} else if ((streamid & 0xF8) == 0x80) {
+				int cnt;
+				u8 *ptr = &(p->buf[off]);
+				ac3_off = (ptr[2] << 8) | ptr[3];
+				cnt = p->count - ac3_off;
+
+				if (cnt > 0 && !get_ac3info(&ptr[3+ac3_off], cnt, &ai)) {
+					p->buf[off+1] = (cnt - off - 3)/ai.framesize + 1;
+					p->buf[off+2] = (ac3_off >> 8) & 0xFF;
+					p->buf[off+3] = (ac3_off) & 0xFF;
+					
+					off += (3 + ac3_off + ai.off);
+					ac3_off +=  p->buf[off+1] * ai.framesize - p->count;
+				}
+				/* else { empty frame ? } */
+			}
+
+			if (ai.framesize) {
+
+				warp2pcm(p, off, ai);
+				goto warped;
+			}
+		}
+
+		if (p->repack_subids) {
+			if (p->cid != AUDIO_STREAM_S)
+				p->func(p->buf, p->count, p->data);
+		} else {
+			if (p->cid != PRIVATE_STREAM1)
+				p->func(p->buf, p->count, p->data);
+		}
+	warped:
+		p->buf[6] = 0x80;
+		p->buf[7] = 0x00;
+		p->buf[8] = 0x00;
+		p->count = 9;
+		if (p->repack_subids && p->cid == PRIVATE_STREAM1 &&
+		    (streamid & 0xF8) == 0x80) {
+			p->count += 4;
+			p->buf[9] = streamid;
+			p->buf[10] = (ac3_off >> 8) & 0xFF;
+			p->buf[11] = (ac3_off) & 0xFF;
+			p->buf[12] = 0;
+		}
+
+		break;
+	case 1:
+		if (p->count < 8) return;
+		p->buf[3] = p->cid;
+		
+		p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8);
+		p->buf[5] = (u8)((p->count-6) & 0x00FF);
+		p->func(p->buf, p->count, p->data);
+	
+		p->buf[6] = 0x0F;
+		p->count = 7;
+		break;
+	}
+}
+
+void send_ipack_rest(ipack *p)
+{
+	if (p->plength != MMAX_PLENGTH-6 || p->found<=6)
+		return;
+	p->plength = p->found-6;
+	p->found = 0;
+	send_ipack(p);
+	reset_ipack(p);
+}
+
+static void write_ipack(ipack *p, u8 *data, int count)
+{
+	u8 headr[3] = { 0x00, 0x00, 0x01} ;
+
+	if (p->count < 6){
+		memcpy(p->buf, headr, 3);
+		p->count = 6;
+	}
+
+	if (p->count + count < p->size){
+		memcpy(p->buf+p->count, data, count);
+		p->count += count;
+	} else {
+		int rest = p->size - p->count;
+		memcpy(p->buf+p->count, data, rest);
+		p->count += rest;
+		send_ipack(p);
+		if (count - rest > 0)
+			write_ipack(p, data+rest, count-rest);
+	}
+}
+
+int instant_repack(u8 *buf, int count, ipack *p)
+{
+	int l;
+	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){
+				p->plen[0] = buf[c];
+				c++;
+				p->plen[1] = buf[c];
+				c++;
+				p->found+=2;
+				p->plength=(p->plen[0]<<8)|p->plen[1];
+ 			} else {
+				p->plen[0] = buf[c];
+				p->found++;
+				return count;
+			}
+			break;
+		case 5:
+			p->plen[1] = buf[c];
+			c++;
+			p->found++;
+			p->plength=(p->plen[0]<<8)|p->plen[1];
+			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 count;
+
+	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 count;
+			}
+
+			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 count;
+				
+				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 count;
+					p->check = buf[c];
+					write_ipack(p, buf+c, 1);
+					c++;
+					p->found++;
+					p->hlength++;
+					p->which = 2;
+					if ( c == count) return count;
+				}
+				
+				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 count;
+				}
+				
+				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 count;
+				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 count;
+					} 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 count;
+					}
+					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 count;
+}
+
+
+
+void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, 
+		  void (*pes_write)(u8 *buf, int count, void *data),
+		  void *priv)
+{
+	init_ipack(pa, IPACKS, pes_write);
+	init_ipack(pv, IPACKS, pes_write);
+	pa->pid = pida;
+	pv->pid = pidv;
+	pa->data = priv;
+	pv->data = priv;
+}
+
+void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
+{
+	u8 off = 0;
+
+	if (!buf || !p ){
+		printk("NULL POINTER IDIOT\n");
+		return;
+	}
+	if (buf[1]&PAY_START) {
+		if (p->plength == MMAX_PLENGTH-6 && p->found>6){
+			p->plength = p->found-6;
+			p->found = 0;
+			send_ipack(p);
+			reset_ipack(p);
+		}
+	}
+	if (buf[3] & ADAPT_FIELD) {  // adaptation field?
+		off = buf[4] + 1;
+		if (off+4 > 187) return;
+	}
+	instant_repack(buf+4+off, TS_SIZE-4-off, p);
+}
+
+#ifdef EXPORT_INFO
+int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi)
+{
+	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:
+		dprintk("Videostream: ASPECT: 1:1");
+		vi->aspect_ratio = 100;        
+		break;
+	case 2:
+		dprintk("Videostream: ASPECT: 4:3");
+                vi->aspect_ratio = 133;        
+		break;
+	case 3:
+		dprintk("Videostream: ASPECT: 16:9");
+                vi->aspect_ratio = 177;        
+		break;
+	case 4:
+		dprintk("Videostream: ASPECT: 2.21:1");
+                vi->aspect_ratio = 221;        
+		break;
+
+        case 5 ... 15:
+		dprintk("Videostream: ASPECT: reserved");
+                vi->aspect_ratio = 0;        
+		break;
+
+        default:
+                vi->aspect_ratio = 0;        
+                return -1;
+	}
+
+	dprintk("  Size = %dx%d",vi->horizontal_size,vi->vertical_size);
+
+        sw = (int)(headr[3]&0x0F);
+
+        switch ( sw ) {
+	case 1:
+		dprintk("  FRate: 23.976 fps");
+                vi->framerate = 24000/1001.;
+		form = -1;
+		break;
+	case 2:
+		dprintk("  FRate: 24 fps");
+                vi->framerate = 24;
+		form = -1;
+		break;
+	case 3:
+		dprintk("  FRate: 25 fps");
+                vi->framerate = 25;
+		form = VIDEO_MODE_PAL;
+		break;
+	case 4:
+		dprintk("  FRate: 29.97 fps");
+                vi->framerate = 30000/1001.;
+		form = VIDEO_MODE_NTSC;
+		break;
+	case 5:
+		dprintk("  FRate: 30 fps");
+                vi->framerate = 30;
+		form = VIDEO_MODE_NTSC;
+		break;
+	case 6:
+		dprintk("  FRate: 50 fps");
+                vi->framerate = 50;
+		form = VIDEO_MODE_PAL;
+		break;
+	case 7:
+		dprintk("  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));
+	
+	dprintk("  BRate: %d Mbit/s\n", (vi->bit_rate));
+        vi->video_format = form;
+
+	vi->off = c-4;
+	return 0;
+}
+
+int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai)
+{
+	uint8_t *headr;
+	int found = 0;
+	int c = 0;
+	int fr = 0;
+
+	while (found < 2 && c < count){
+		uint8_t b[2];
+		memcpy( b, mbuf+c, 2);
+
+		if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
+			found = 2;
+		else {
+			c++;
+		}
+	}	
+
+	if (!found) return -1;
+
+	if (c+3 >= count) return -1;
+        headr = mbuf+c;
+
+	ai->layer = (headr[1] & 0x06) >> 1;
+
+	dprintk("Audiostream: Layer: %d", 4-ai->layer);
+
+	ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000;
+
+#ifdef DEBUG_FILTER
+	if (ai->bit_rate == 0)
+		printk("  Bit rate: free");
+	else if (ai->bit_rate == 0xf)
+		printk("  BRate: reserved");
+	else
+		printk("  BRate: %d kb/s", ai->bit_rate/1000);
+#endif
+
+	fr = (headr[2] & 0x0c ) >> 2;
+	ai->frequency = freq[fr]*100;
+#ifdef DEBUG_FILTER
+	if (ai->frequency == 3)
+		printk("  Freq: reserved\n");
+	else
+		printk("  Freq: %d kHz\n",ai->frequency); 
+#endif
+	ai->off = c;
+	return 0;
+}
+
+int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai)
+#else /* EXPORT_INFO */
+static int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai)
+#endif /* EXPORT_INFO */
+{
+	uint8_t *headr;
+	int found = 0;
+	int c = 0;
+	uint8_t frame = 0;
+	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;
+	dprintk("Audiostream: AC3");
+
+	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;
+	dprintk ("  BRate: %d kB/s", ai->bit_rate/1000);
+
+	fr = (headr[2] & 0xc0) >> 6;
+	ai->frequency = ac3_freq[fr]*100;
+	dprintk ("  Freq: %d Hz\n", ai->frequency);
+
+        ai->bsid  = (headr[3] >> 3) & 0x1f;;
+        ai->bsmod = (headr[3] & 0x07);;
+	dprintk ("  Bsid/Bsmod: %d/%d\n", ai->bsid, ai->bsmod);
+
+	ai->framesize = ac3_frames[fr][frame >> 1];
+	if ((frame & 1) &&  (fr == 1)) ai->framesize++;
+	ai->framesize = ai->framesize << 1;
+	dprintk ("  Framesize %dB\n", ai->framesize);
+
+	return 0;
+}
+
+uint8_t *skip_pes_header(uint8_t **bufp)
+{
+        uint8_t *inbuf = *bufp;
+        uint8_t *buf = inbuf;
+        uint8_t *pts = NULL;
+        int skip = 0;
+
+int mpeg1_skip_table[16] = {
+        1, 0xffff,      5,     10, 0xffff, 0xffff, 0xffff, 0xffff,
+        0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
+};
+
+
+        if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
+                if (buf[7] & PTS_ONLY)
+                        pts = buf+9;
+                else pts = NULL;
+                buf = inbuf + 9 + inbuf[8];
+        } else {        /* mpeg1 */
+                for (buf = inbuf + 6; *buf == 0xff; buf++)
+                        if (buf == inbuf + 6 + 16) {
+                                break;
+                        }
+                if ((*buf & 0xc0) == 0x40)
+                        buf += 2;
+                skip = mpeg1_skip_table [*buf >> 4];
+                if (skip == 5 || skip == 10) pts = buf;
+                else pts = NULL;
+
+                buf += mpeg1_skip_table [*buf >> 4];
+        }
+
+        *bufp = buf;
+        return pts;
+}
+
+#ifndef USER_SPACE
+EXPORT_SYMBOL(pes2ts_init);
+EXPORT_SYMBOL(pes2ts);
+EXPORT_SYMBOL(reset_ipack);
+EXPORT_SYMBOL(init_ipack);
+EXPORT_SYMBOL(free_ipack);
+EXPORT_SYMBOL(send_ipack);
+EXPORT_SYMBOL(send_ipack_rest);
+EXPORT_SYMBOL(instant_repack);
+EXPORT_SYMBOL(setup_ts2pes);
+EXPORT_SYMBOL(ts_to_pes);
+EXPORT_SYMBOL(skip_pes_header);
+EXPORT_SYMBOL(enable2pcm);
+EXPORT_SYMBOL(disable2pcm);
+#endif
--- dvb_filter.h
+++ dvb_filter.h	Fri Nov 29 13:35:17 2002
@@ -0,0 +1,180 @@
+#ifndef _DVB_FILTER_H_
+#define _DVB_FILTER_H_
+
+#ifndef USER_SPACE
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#endif
+
+#ifndef USER_SPACE
+#ifdef __DVB_PACK__
+#include <ost/demux.h>
+#else
+#include <linux/ost/demux.h>
+#endif
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <sys/types.h>
+#define __KERNEL__
+#include <asm/types.h>
+#undef __KERNEL__
+typedef u8 uint_8;
+#include <linux/videodev.h>
+#define vfree free
+#define vmalloc malloc
+#define printk(fmt, args...) fprintf(stderr, fmt, ##args)
+#endif
+
+#define aAC3   0x80
+#define aDTS   0x88
+#define aLPCM  0xA0
+#define aMPEG  0xC0
+
+typedef int (pes2ts_cb_t) (void *, unsigned char *);
+
+typedef struct pes2ts_s {
+	unsigned char buf[188];
+        unsigned char cc;
+        pes2ts_cb_t *cb;
+	void *priv;
+} pes2ts_t;
+
+void pes2ts_init(pes2ts_t *p2ts, unsigned short pid, 
+		 pes2ts_cb_t *cb, void *priv);
+int pes2ts(pes2ts_t *p2ts, unsigned char *pes, int len);
+
+
+#define PROG_STREAM_MAP  0xBC
+#define PRIVATE_STREAM1  0xBD
+#define PADDING_STREAM   0xBE
+#define PRIVATE_STREAM2  0xBF
+#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
+
+//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 (256*MAX_PLENGTH)
+
+#ifndef IPACKS
+#define IPACKS 2048
+#endif
+
+typedef struct ipack_s {
+	int size;
+	int found;
+	u8 *buf;
+	u8 cid;
+	uint32_t plength;
+	u8 plen[2];
+	u8 flag1;
+	u8 flag2;
+	u8 hlength;
+	u8 pts[5];
+	u16 *pid;
+	int mpeg;
+	u8 check;
+	int which;
+	int done;
+	void *data;
+	void (*func)(u8 *buf,  int size, void *priv);
+	int count;
+	int repack_subids;
+	int init_subids;
+} ipack;
+
+typedef struct video_i{
+	u32 horizontal_size;
+	u32 vertical_size       ;
+	u32 aspect_ratio        ;
+	double framerate        ;
+	u32 video_format;
+	u32 bit_rate    ;
+	u32 comp_bit_rate       ;
+	u32 vbv_buffer_size;
+	u32 CSPF                ;
+	u32 off;
+} VideoInfo;            
+
+typedef struct audio_i{
+	int layer               ;
+	u32 bit_rate    ;
+	u32 frequency   ;
+	u32 mode                ;
+	u32 mode_extension ;
+	u32 emphasis    ;
+	u32 framesize;
+	u32 off;
+	u8 bsid;
+	u8 bsmod;
+} AudioInfo;
+
+extern void reset_ipack(ipack *p);
+extern int instant_repack(u8 *buf, int count, ipack *p);
+extern void init_ipack(ipack *p, int size,
+		void (*func)(u8 *buf,  int size, void *priv));
+extern void free_ipack(ipack * p);
+extern void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, 
+		  void (*pes_write)(u8 *buf, int count, void *data),
+		  void *priv);
+extern void ts_to_pes(ipack *p, u8 *buf); 
+extern void send_ipack(ipack *p);
+extern void send_ipack_rest(ipack *p);
+extern void disable2pcm(ipack *p);
+extern void enable2pcm(ipack *p);
+#ifdef EXPORT_INFO
+int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai);
+int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai);
+int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi);
+#endif
+extern uint8_t *skip_pes_header(uint8_t **bufp);
+#endif


-- 
Info:
To unsubscribe send a mail to listar@linuxtv.org with "unsubscribe linux-dvb" as subject.



Home | Main Index | Thread Index