• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "dvb_filter.h"
2 #include "av7110_ipack.h"
3 #include <linux/string.h>	/* for memcpy() */
4 #include <linux/vmalloc.h>
5 
6 
av7110_ipack_reset(struct ipack * p)7 void av7110_ipack_reset(struct ipack *p)
8 {
9 	p->found = 0;
10 	p->cid = 0;
11 	p->plength = 0;
12 	p->flag1 = 0;
13 	p->flag2 = 0;
14 	p->hlength = 0;
15 	p->mpeg = 0;
16 	p->check = 0;
17 	p->which = 0;
18 	p->done = 0;
19 	p->count = 0;
20 }
21 
22 
av7110_ipack_init(struct ipack * p,int size,void (* func)(u8 * buf,int size,void * priv))23 int av7110_ipack_init(struct ipack *p, int size,
24 		      void (*func)(u8 *buf, int size, void *priv))
25 {
26 	if (!(p->buf = vmalloc(size*sizeof(u8)))) {
27 		printk(KERN_WARNING "Couldn't allocate memory for ipack\n");
28 		return -ENOMEM;
29 	}
30 	p->size = size;
31 	p->func = func;
32 	p->repack_subids = 0;
33 	av7110_ipack_reset(p);
34 	return 0;
35 }
36 
37 
av7110_ipack_free(struct ipack * p)38 void av7110_ipack_free(struct ipack *p)
39 {
40 	vfree(p->buf);
41 }
42 
43 
send_ipack(struct ipack * p)44 static void send_ipack(struct ipack *p)
45 {
46 	int off;
47 	struct dvb_audio_info ai;
48 	int ac3_off = 0;
49 	int streamid = 0;
50 	int nframes = 0;
51 	int f = 0;
52 
53 	switch (p->mpeg) {
54 	case 2:
55 		if (p->count < 10)
56 			return;
57 		p->buf[3] = p->cid;
58 		p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
59 		p->buf[5] = (u8)((p->count - 6) & 0x00ff);
60 		if (p->repack_subids && p->cid == PRIVATE_STREAM1) {
61 			off = 9 + p->buf[8];
62 			streamid = p->buf[off];
63 			if ((streamid & 0xf8) == 0x80) {
64 				ai.off = 0;
65 				ac3_off = ((p->buf[off + 2] << 8)|
66 					   p->buf[off + 3]);
67 				if (ac3_off < p->count)
68 					f = dvb_filter_get_ac3info(p->buf + off + 3 + ac3_off,
69 								   p->count - ac3_off, &ai, 0);
70 				if (!f) {
71 					nframes = (p->count - off - 3 - ac3_off) /
72 						ai.framesize + 1;
73 					p->buf[off + 2] = (ac3_off >> 8) & 0xff;
74 					p->buf[off + 3] = (ac3_off) & 0xff;
75 					p->buf[off + 1] = nframes;
76 					ac3_off +=  nframes * ai.framesize - p->count;
77 				}
78 			}
79 		}
80 		p->func(p->buf, p->count, p->data);
81 
82 		p->buf[6] = 0x80;
83 		p->buf[7] = 0x00;
84 		p->buf[8] = 0x00;
85 		p->count = 9;
86 		if (p->repack_subids && p->cid == PRIVATE_STREAM1
87 		    && (streamid & 0xf8) == 0x80) {
88 			p->count += 4;
89 			p->buf[9] = streamid;
90 			p->buf[10] = (ac3_off >> 8) & 0xff;
91 			p->buf[11] = (ac3_off) & 0xff;
92 			p->buf[12] = 0;
93 		}
94 		break;
95 
96 	case 1:
97 		if (p->count < 8)
98 			return;
99 		p->buf[3] = p->cid;
100 		p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
101 		p->buf[5] = (u8)((p->count - 6) & 0x00ff);
102 		p->func(p->buf, p->count, p->data);
103 
104 		p->buf[6] = 0x0f;
105 		p->count = 7;
106 		break;
107 	}
108 }
109 
110 
av7110_ipack_flush(struct ipack * p)111 void av7110_ipack_flush(struct ipack *p)
112 {
113 	if (p->plength != MMAX_PLENGTH - 6 || p->found <= 6)
114 		return;
115 	p->plength = p->found - 6;
116 	p->found = 0;
117 	send_ipack(p);
118 	av7110_ipack_reset(p);
119 }
120 
121 
write_ipack(struct ipack * p,const u8 * data,int count)122 static void write_ipack(struct ipack *p, const u8 *data, int count)
123 {
124 	u8 headr[3] = { 0x00, 0x00, 0x01 };
125 
126 	if (p->count < 6) {
127 		memcpy(p->buf, headr, 3);
128 		p->count = 6;
129 	}
130 
131 	if (p->count + count < p->size){
132 		memcpy(p->buf+p->count, data, count);
133 		p->count += count;
134 	} else {
135 		int rest = p->size - p->count;
136 		memcpy(p->buf+p->count, data, rest);
137 		p->count += rest;
138 		send_ipack(p);
139 		if (count - rest > 0)
140 			write_ipack(p, data + rest, count - rest);
141 	}
142 }
143 
144 
av7110_ipack_instant_repack(const u8 * buf,int count,struct ipack * p)145 int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
146 {
147 	int l;
148 	int c = 0;
149 
150 	while (c < count && (p->mpeg == 0 ||
151 			     (p->mpeg == 1 && p->found < 7) ||
152 			     (p->mpeg == 2 && p->found < 9))
153 	       &&  (p->found < 5 || !p->done)) {
154 		switch (p->found) {
155 		case 0:
156 		case 1:
157 			if (buf[c] == 0x00)
158 				p->found++;
159 			else
160 				p->found = 0;
161 			c++;
162 			break;
163 		case 2:
164 			if (buf[c] == 0x01)
165 				p->found++;
166 			else if (buf[c] == 0)
167 				p->found = 2;
168 			else
169 				p->found = 0;
170 			c++;
171 			break;
172 		case 3:
173 			p->cid = 0;
174 			switch (buf[c]) {
175 			case PROG_STREAM_MAP:
176 			case PRIVATE_STREAM2:
177 			case PROG_STREAM_DIR:
178 			case ECM_STREAM     :
179 			case EMM_STREAM     :
180 			case PADDING_STREAM :
181 			case DSM_CC_STREAM  :
182 			case ISO13522_STREAM:
183 				p->done = 1;
184 				/* fall through */
185 			case PRIVATE_STREAM1:
186 			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
187 			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
188 				p->found++;
189 				p->cid = buf[c];
190 				c++;
191 				break;
192 			default:
193 				p->found = 0;
194 				break;
195 			}
196 			break;
197 
198 		case 4:
199 			if (count-c > 1) {
200 				p->plen[0] = buf[c];
201 				c++;
202 				p->plen[1] = buf[c];
203 				c++;
204 				p->found += 2;
205 				p->plength = (p->plen[0] << 8) | p->plen[1];
206 			} else {
207 				p->plen[0] = buf[c];
208 				p->found++;
209 				return count;
210 			}
211 			break;
212 		case 5:
213 			p->plen[1] = buf[c];
214 			c++;
215 			p->found++;
216 			p->plength = (p->plen[0] << 8) | p->plen[1];
217 			break;
218 		case 6:
219 			if (!p->done) {
220 				p->flag1 = buf[c];
221 				c++;
222 				p->found++;
223 				if ((p->flag1 & 0xc0) == 0x80)
224 					p->mpeg = 2;
225 				else {
226 					p->hlength = 0;
227 					p->which = 0;
228 					p->mpeg = 1;
229 					p->flag2 = 0;
230 				}
231 			}
232 			break;
233 
234 		case 7:
235 			if (!p->done && p->mpeg == 2) {
236 				p->flag2 = buf[c];
237 				c++;
238 				p->found++;
239 			}
240 			break;
241 
242 		case 8:
243 			if (!p->done && p->mpeg == 2) {
244 				p->hlength = buf[c];
245 				c++;
246 				p->found++;
247 			}
248 			break;
249 		}
250 	}
251 
252 	if (c == count)
253 		return count;
254 
255 	if (!p->plength)
256 		p->plength = MMAX_PLENGTH - 6;
257 
258 	if (p->done || ((p->mpeg == 2 && p->found >= 9) ||
259 			(p->mpeg == 1 && p->found >= 7))) {
260 		switch (p->cid) {
261 		case AUDIO_STREAM_S ... AUDIO_STREAM_E:
262 		case VIDEO_STREAM_S ... VIDEO_STREAM_E:
263 		case PRIVATE_STREAM1:
264 			if (p->mpeg == 2 && p->found == 9) {
265 				write_ipack(p, &p->flag1, 1);
266 				write_ipack(p, &p->flag2, 1);
267 				write_ipack(p, &p->hlength, 1);
268 			}
269 
270 			if (p->mpeg == 1 && p->found == 7)
271 				write_ipack(p, &p->flag1, 1);
272 
273 			if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&
274 			    p->found < 14) {
275 				while (c < count && p->found < 14) {
276 					p->pts[p->found - 9] = buf[c];
277 					write_ipack(p, buf + c, 1);
278 					c++;
279 					p->found++;
280 				}
281 				if (c == count)
282 					return count;
283 			}
284 
285 			if (p->mpeg == 1 && p->which < 2000) {
286 
287 				if (p->found == 7) {
288 					p->check = p->flag1;
289 					p->hlength = 1;
290 				}
291 
292 				while (!p->which && c < count &&
293 				       p->check == 0xff){
294 					p->check = buf[c];
295 					write_ipack(p, buf + c, 1);
296 					c++;
297 					p->found++;
298 					p->hlength++;
299 				}
300 
301 				if (c == count)
302 					return count;
303 
304 				if ((p->check & 0xc0) == 0x40 && !p->which) {
305 					p->check = buf[c];
306 					write_ipack(p, buf + c, 1);
307 					c++;
308 					p->found++;
309 					p->hlength++;
310 
311 					p->which = 1;
312 					if (c == count)
313 						return count;
314 					p->check = buf[c];
315 					write_ipack(p, buf + c, 1);
316 					c++;
317 					p->found++;
318 					p->hlength++;
319 					p->which = 2;
320 					if (c == count)
321 						return count;
322 				}
323 
324 				if (p->which == 1) {
325 					p->check = buf[c];
326 					write_ipack(p, buf + c, 1);
327 					c++;
328 					p->found++;
329 					p->hlength++;
330 					p->which = 2;
331 					if (c == count)
332 						return count;
333 				}
334 
335 				if ((p->check & 0x30) && p->check != 0xff) {
336 					p->flag2 = (p->check & 0xf0) << 2;
337 					p->pts[0] = p->check;
338 					p->which = 3;
339 				}
340 
341 				if (c == count)
342 					return count;
343 				if (p->which > 2){
344 					if ((p->flag2 & PTS_DTS_FLAGS) == PTS_ONLY) {
345 						while (c < count && p->which < 7) {
346 							p->pts[p->which - 2] = buf[c];
347 							write_ipack(p, buf + c, 1);
348 							c++;
349 							p->found++;
350 							p->which++;
351 							p->hlength++;
352 						}
353 						if (c == count)
354 							return count;
355 					} else if ((p->flag2 & PTS_DTS_FLAGS) == PTS_DTS) {
356 						while (c < count && p->which < 12) {
357 							if (p->which < 7)
358 								p->pts[p->which - 2] = buf[c];
359 							write_ipack(p, buf + c, 1);
360 							c++;
361 							p->found++;
362 							p->which++;
363 							p->hlength++;
364 						}
365 						if (c == count)
366 							return count;
367 					}
368 					p->which = 2000;
369 				}
370 
371 			}
372 
373 			while (c < count && p->found < p->plength + 6) {
374 				l = count - c;
375 				if (l + p->found > p->plength + 6)
376 					l = p->plength + 6 - p->found;
377 				write_ipack(p, buf + c, l);
378 				p->found += l;
379 				c += l;
380 			}
381 			break;
382 		}
383 
384 
385 		if (p->done) {
386 			if (p->found + count - c < p->plength + 6) {
387 				p->found += count - c;
388 				c = count;
389 			} else {
390 				c += p->plength + 6 - p->found;
391 				p->found = p->plength + 6;
392 			}
393 		}
394 
395 		if (p->plength && p->found == p->plength + 6) {
396 			send_ipack(p);
397 			av7110_ipack_reset(p);
398 			if (c < count)
399 				av7110_ipack_instant_repack(buf + c, count - c, p);
400 		}
401 	}
402 	return count;
403 }
404