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