diff options
Diffstat (limited to 'linux/drivers/media/dvb/av7110')
-rw-r--r-- | linux/drivers/media/dvb/av7110/Makefile | 2 | ||||
-rw-r--r-- | linux/drivers/media/dvb/av7110/av7110.c | 35 | ||||
-rw-r--r-- | linux/drivers/media/dvb/av7110/av7110_ipack.c | 404 | ||||
-rw-r--r-- | linux/drivers/media/dvb/av7110/av7110_ipack.h | 13 |
4 files changed, 436 insertions, 18 deletions
diff --git a/linux/drivers/media/dvb/av7110/Makefile b/linux/drivers/media/dvb/av7110/Makefile index 809a68d3f..5a9fd0c0c 100644 --- a/linux/drivers/media/dvb/av7110/Makefile +++ b/linux/drivers/media/dvb/av7110/Makefile @@ -2,7 +2,7 @@ # Makefile for the kernel AV7110 DVB device driver # -dvb-ttpci-objs := av7110.o av7110_ir.o +dvb-ttpci-objs := av7110.o av7110_ipack.o av7110_ir.o obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o diff --git a/linux/drivers/media/dvb/av7110/av7110.c b/linux/drivers/media/dvb/av7110/av7110.c index 8acea0af7..7662a8b78 100644 --- a/linux/drivers/media/dvb/av7110/av7110.c +++ b/linux/drivers/media/dvb/av7110/av7110.c @@ -76,6 +76,7 @@ // #include "compat.h" #include "av7110.h" +#include "av7110_ipack.h" static int AV_StartPlay(av7110_t *av7110, int av); @@ -464,8 +465,8 @@ AV_StartPlay(av7110_t *av7110, int av) outcom(av7110, COMTYPE_REC_PLAY, __Stop, 0); if (av7110->playing == RP_NONE) { - dvb_filter_ipack_reset(&av7110->ipack[0]); - dvb_filter_ipack_reset(&av7110->ipack[1]); + av7110_ipack_reset(&av7110->ipack[0]); + av7110_ipack_reset(&av7110->ipack[1]); } av7110->playing|=av; @@ -2536,11 +2537,11 @@ dvb_play(av7110_t *av7110, const u8 *buf, if (umem) { if (copy_from_user(av7110->kbuf[type], buf, n)) return -EFAULT; - dvb_filter_instant_repack(av7110->kbuf[type], n, - &av7110->ipack[type]); + av7110_ipack_instant_repack(av7110->kbuf[type], n, + &av7110->ipack[type]); } else { - dvb_filter_instant_repack((u8 *)buf, n, - &av7110->ipack[type]); + av7110_ipack_instant_repack(buf, n, + &av7110->ipack[type]); } todo -= n; buf += n; @@ -2573,8 +2574,8 @@ dvb_aplay(av7110_t *av7110, const u8 *buf, n=IPACKS*2; if (copy_from_user(av7110->kbuf[type], buf, n)) return -EFAULT; - dvb_filter_instant_repack(av7110->kbuf[type], n, - &av7110->ipack[type]); + av7110_ipack_instant_repack(av7110->kbuf[type], n, + &av7110->ipack[type]); // memcpy(dvb->kbuf[type], buf, n); todo -= n; buf += n; @@ -3002,7 +3003,7 @@ av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len) return -1; } if (buf[1] & 0x40) - dvb_filter_ipack_flush(ipack); + av7110_ipack_flush(ipack); if (buf[3] & 0x20) { // adaptation field? len -= buf[4]+1; @@ -3011,7 +3012,7 @@ av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len) return 0; } - dvb_filter_instant_repack(buf+4, len-4, &av7110->ipack[feed->pes_type]); + av7110_ipack_instant_repack(buf+4, len-4, &av7110->ipack[feed->pes_type]); return 0; } @@ -3602,7 +3603,7 @@ play_iframe(av7110_t *av7110, u8 *buf, unsigned int len, int nonblock) for (i=0; i<n; i++) dvb_play(av7110, buf, len, 0, 1, 1); - dvb_filter_ipack_flush(&av7110->ipack[1]); + av7110_ipack_flush(&av7110->ipack[1]); } @@ -3767,7 +3768,7 @@ dvb_video_ioctl(struct inode *inode, struct file *file, case VIDEO_CLEAR_BUFFER: ring_buffer_flush(&av7110->avout); - dvb_filter_ipack_reset(&av7110->ipack[1]); + av7110_ipack_reset(&av7110->ipack[1]); if (av7110->playing==RP_AV) { outcom(av7110, COMTYPE_REC_PLAY, @@ -3890,7 +3891,7 @@ dvb_audio_ioctl(struct inode *inode, struct file *file, case AUDIO_CLEAR_BUFFER: ring_buffer_flush(&av7110->aout); - dvb_filter_ipack_reset(&av7110->ipack[0]); + av7110_ipack_reset(&av7110->ipack[0]); if (av7110->playing==RP_AV) outcom(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0); @@ -4435,9 +4436,9 @@ int av7110_attach (struct saa7146_dev* dev) av7110->vidmode=VIDEO_MODE_PAL; - dvb_filter_ipack_init(&av7110->ipack[0], IPACKS, play_audio_cb); + av7110_ipack_init(&av7110->ipack[0], IPACKS, play_audio_cb); av7110->ipack[0].data=(void *) av7110; - dvb_filter_ipack_init(&av7110->ipack[1], IPACKS, play_video_cb); + av7110_ipack_init(&av7110->ipack[1], IPACKS, play_video_cb); av7110->ipack[1].data=(void *) av7110; @@ -4563,8 +4564,8 @@ int av7110_detach (struct saa7146_dev* saa) saa7146_write(av7110->dev, ISR,(MASK_19 | MASK_03)); ci_ll_release(&av7110->ci_rbuffer, &av7110->ci_wbuffer); - dvb_filter_ipack_free(&av7110->ipack[0]); - dvb_filter_ipack_free(&av7110->ipack[1]); + av7110_ipack_free(&av7110->ipack[0]); + av7110_ipack_free(&av7110->ipack[1]); vfree(av7110->iobuf); pci_free_consistent(saa->pci, 8192, av7110->debi_virt, av7110->debi_bus); diff --git a/linux/drivers/media/dvb/av7110/av7110_ipack.c b/linux/drivers/media/dvb/av7110/av7110_ipack.c new file mode 100644 index 000000000..7058839ad --- /dev/null +++ b/linux/drivers/media/dvb/av7110/av7110_ipack.c @@ -0,0 +1,404 @@ +#include "dvb_filter.h" +#include "av7110_ipack.h" + + + +void av7110_ipack_reset(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; +} + + +void av7110_ipack_init(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; + av7110_ipack_reset(p); +} + + +void av7110_ipack_free(ipack * p) +{ + if (p->buf) vfree(p->buf); +} + + +static +void send_ipack(ipack *p) +{ + int off; + AudioInfo ai; + int ac3_off = 0; + int streamid=0; + int nframes= 0; + int f=0; + + switch ( p->mpeg ){ + case 2: + if (p->count < 10) return; + p->buf[3] = p->cid; + + 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 ((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+2] = (ac3_off >> 8)& 0xFF; + p->buf[off+3] = (ac3_off)& 0xFF; + p->buf[off+1] = nframes; + + ac3_off += nframes * ai.framesize - + p->count; + } + } + } + p->func(p->buf, p->count, p->data); + + 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 av7110_ipack_flush(ipack *p) +{ + if (p->plength != MMAX_PLENGTH-6 || p->found<=6) + return; + p->plength = p->found-6; + p->found = 0; + send_ipack(p); + av7110_ipack_reset(p); +} + + +static +void write_ipack(ipack *p, const 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 av7110_ipack_instant_repack (const 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); + av7110_ipack_reset(p); + if (c < count) + av7110_ipack_instant_repack(buf+c, count-c, p); + } + } + return count; +} + diff --git a/linux/drivers/media/dvb/av7110/av7110_ipack.h b/linux/drivers/media/dvb/av7110/av7110_ipack.h new file mode 100644 index 000000000..d1c995aff --- /dev/null +++ b/linux/drivers/media/dvb/av7110/av7110_ipack.h @@ -0,0 +1,13 @@ +#ifndef _AV7110_IPACK_H_ +#define _AV7110_IPACK_H_ + +extern void av7110_ipack_init(ipack *p, int size, + void (*func)(u8 *buf, int size, void *priv)); + +extern void av7110_ipack_reset(ipack *p); +extern int av7110_ipack_instant_repack(const u8 *buf, int count, ipack *p); +extern void av7110_ipack_free(ipack * p); +extern void av7110_ipack_flush(ipack *p); + +#endif + |