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