Mailing List archive

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

[vdr] Re: AC3 over Soundcard (live and replay) (Was: AC3 5.1 - can someone "fix" -a in VDR 1.1.x - Please :)



On Tue, Jan 28, 2003 at 09:09:45PM +0100, Gregoire Favre wrote:
> Hello,
> 
> does that mean that we need a soundcard to use AC3 with DVB?
> 
> It took me lots of hard work to have an optical cable connecting my 5.1
> to the DVB-s (I am not an electronic fan at all...), and all sent to
> this list wasn't working for me...
> 
> Wouldn't it be possible to have a plugin that use the output of the
> DVB-s?
> 
> Should I need a souncard?
> Or the:
> * It should be possible to do the `AC3 warpped into PCM'
>   within the DVB driver (even for Live TV!) because the
>   full featured cards provide a S/P-DIF out.

If the firmware is stable enough to do transfer the Dolby digital pid
into kernel space and receive the AC3 warped into PCM which its self
is warped into a private stream 1 with the sub id for linear PCM [1]
_together_ with receiving OSD bitmaps and transferring EPG data and/or
recording data ...  this _will_ work!

The last time I've tried that I've got on four starts three freezes.
OK it was an old driver with the first firmware for the NEWSTRUCT.

Maybe this is possible with the current driver and its firmware.
Nevertheless I've never got any answer from convergence nor from
the Metzler brothers on my questions and submitted code.
(The question was: Is it possible to do that in the firmware without
 transfer into kernel space).

I'm not willingly to do any more to do more investigation in that
direction.  IMHO  it can also done in users space if the firmware
is stable (and fast) enough.  OK, the disadvantage is the latency
lost due to the copy_to_user/copy_from_user together with the necessary
schedule() calls ... because the driver doesn't know about memory
mapping.


        Werner

 [1] ... for the sub id I've used the following extension which
     I've used in send_ipack() in dvb_filter.c ... maybe it could
     be also used in instant_repack() directly.  The value
     lpcmh[6] == 0x81 seems to enable none audio S/P-DIF transmissions
     (at least my Pioneer VSA-E07 belives that) besides the magic
     PCM start words for none audio in the 16 bit payload of the
     32bit S/P-DIF words.

------------------------------- warp2pcm.h ---------------------------
#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_ */
------------------------------- warp2pcm.h ---------------------------


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



Home | Main Index | Thread Index