xref: /linux/drivers/staging/media/av7110/dvb_filter.c (revision c771600c6af14749609b49565ffb4cac2959710d)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/module.h>
4 #include <linux/string.h>
5 #include "dvb_filter.h"
6 
7 static u32 freq[4] = {480, 441, 320, 0};
8 
9 static unsigned int ac3_bitrates[32] = {
10 	32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640,
11 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
12 };
13 
14 static u32 ac3_frames[3][32] = {
15 	{64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 640, 768, 896, 1024,
16 	 1152, 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
17 	{69, 87, 104, 121, 139, 174, 208, 243, 278, 348, 417, 487, 557, 696, 835, 975, 1114,
18 	 1253, 1393, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
19 	{96, 120, 144, 168, 192, 240, 288, 336, 384, 480, 576, 672, 768, 960, 1152, 1344,
20 	 1536, 1728, 1920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
21 };
22 
dvb_filter_get_ac3info(u8 * mbuf,int count,struct dvb_audio_info * ai,int pr)23 int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
24 {
25 	u8 *headr;
26 	int found = 0;
27 	int c = 0;
28 	u8 frame = 0;
29 	int fr = 0;
30 
31 	while (!found  && c < count) {
32 		u8 *b = mbuf + c;
33 
34 		if (b[0] == 0x0b &&  b[1] == 0x77)
35 			found = 1;
36 		else
37 			c++;
38 	}
39 
40 	if (!found)
41 		return -1;
42 
43 	ai->off = c;
44 	if (c + 5 >= count)
45 		return -1;
46 
47 	ai->layer = 0;  // 0 for AC3
48 	headr = mbuf + c + 2;
49 
50 	frame = (headr[2] & 0x3f);
51 	ai->bit_rate = ac3_bitrates[frame >> 1] * 1000;
52 
53 	ai->frequency = (headr[2] & 0xc0) >> 6;
54 	fr = (headr[2] & 0xc0) >> 6;
55 	ai->frequency = freq[fr] * 100;
56 
57 	ai->framesize = ac3_frames[fr][frame >> 1];
58 	if ((frame & 1) && (fr == 1))
59 		ai->framesize++;
60 	ai->framesize = ai->framesize << 1;
61 
62 	if (pr)
63 		pr_info("Audiostream: AC3, BRate: %d kb/s, Freq: %d Hz, Framesize %d\n",
64 			(int)ai->bit_rate / 1000, (int)ai->frequency, (int)ai->framesize);
65 
66 	return 0;
67 }
68 
dvb_filter_pes2ts_init(struct dvb_filter_pes2ts * p2ts,unsigned short pid,dvb_filter_pes2ts_cb_t * cb,void * priv)69 void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
70 			    dvb_filter_pes2ts_cb_t *cb, void *priv)
71 {
72 	unsigned char *buf = p2ts->buf;
73 
74 	buf[0] = 0x47;
75 	buf[1] = (pid >> 8);
76 	buf[2] = pid & 0xff;
77 	p2ts->cc = 0;
78 	p2ts->cb = cb;
79 	p2ts->priv = priv;
80 }
81 
dvb_filter_pes2ts(struct dvb_filter_pes2ts * p2ts,unsigned char * pes,int len,int payload_start)82 int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
83 		      int len, int payload_start)
84 {
85 	unsigned char *buf = p2ts->buf;
86 	int ret = 0, rest;
87 
88 	//len=6+((pes[4]<<8)|pes[5]);
89 
90 	if (payload_start)
91 		buf[1] |= 0x40;
92 	else
93 		buf[1] &= ~0x40;
94 	while (len >= 184) {
95 		buf[3] = 0x10 | ((p2ts->cc++) & 0x0f);
96 		memcpy(buf + 4, pes, 184);
97 		ret = p2ts->cb(p2ts->priv, buf);
98 		if (ret)
99 			return ret;
100 		len -= 184; pes += 184;
101 		buf[1] &= ~0x40;
102 	}
103 	if (!len)
104 		return 0;
105 	buf[3] = 0x30 | ((p2ts->cc++) & 0x0f);
106 	rest = 183 - len;
107 	if (rest) {
108 		buf[5] = 0x00;
109 		if (rest - 1)
110 			memset(buf + 6, 0xff, rest - 1);
111 	}
112 	buf[4] = rest;
113 	memcpy(buf + 5 + rest, pes, len);
114 	return p2ts->cb(p2ts->priv, buf);
115 }
116