mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-31 20:42:39 +00:00 
			
		
		
		
	 80887a59c2
			
		
	
	
		80887a59c2
		
	
	
	
	
		
			
			printk() calls should include appropriate KERN_* constant. Signed-off-by: Christophe Lucas <clucas@rotomalug.org> Signed-off-by: Domen Puncer <domen@coderock.org> Signed-off-by: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
		
			
				
	
	
		
			404 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			404 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "dvb_filter.h"
 | |
| #include "av7110_ipack.h"
 | |
| #include <linux/string.h>	/* for memcpy() */
 | |
| #include <linux/vmalloc.h>
 | |
| 
 | |
| 
 | |
| void av7110_ipack_reset(struct 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;
 | |
| }
 | |
| 
 | |
| 
 | |
| int av7110_ipack_init(struct ipack *p, int size,
 | |
| 		      void (*func)(u8 *buf, int size, void *priv))
 | |
| {
 | |
| 	if (!(p->buf = vmalloc(size*sizeof(u8)))) {
 | |
| 		printk(KERN_WARNING "Couldn't allocate memory for ipack\n");
 | |
| 		return -ENOMEM;
 | |
| 	}
 | |
| 	p->size = size;
 | |
| 	p->func = func;
 | |
| 	p->repack_subids = 0;
 | |
| 	av7110_ipack_reset(p);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| void av7110_ipack_free(struct ipack *p)
 | |
| {
 | |
| 	vfree(p->buf);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void send_ipack(struct ipack *p)
 | |
| {
 | |
| 	int off;
 | |
| 	struct dvb_audio_info 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 = dvb_filter_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(struct 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(struct 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, struct 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;
 | |
| 				/* fall through */
 | |
| 			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;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	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;
 | |
| }
 |