Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / media / dvb-core / dvb_filter.c
diff --git a/kernel/drivers/media/dvb-core/dvb_filter.c b/kernel/drivers/media/dvb-core/dvb_filter.c
new file mode 100644 (file)
index 0000000..772003f
--- /dev/null
@@ -0,0 +1,603 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include "dvb_filter.h"
+
+#if 0
+static unsigned int bitrates[3][16] =
+{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
+ {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
+ {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
+#endif
+
+static u32 freq[4] = {480, 441, 320, 0};
+
+static unsigned int ac3_bitrates[32] =
+    {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
+     0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+static u32 ac3_frames[3][32] =
+    {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
+      1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
+     {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
+      1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
+     {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
+      1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+
+
+
+#if 0
+static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv,
+                 void (*pes_write)(u8 *buf, int count, void *data),
+                 void *priv)
+{
+       dvb_filter_ipack_init(pa, IPACKS, pes_write);
+       dvb_filter_ipack_init(pv, IPACKS, pes_write);
+       pa->pid = pida;
+       pv->pid = pidv;
+       pa->data = priv;
+       pv->data = priv;
+}
+#endif
+
+#if 0
+static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
+{
+       u8 off = 0;
+
+       if (!buf || !p ){
+               printk("NULL POINTER IDIOT\n");
+               return;
+       }
+       if (buf[1]&PAY_START) {
+               if (p->plength == MMAX_PLENGTH-6 && p->found>6){
+                       p->plength = p->found-6;
+                       p->found = 0;
+                       send_ipack(p);
+                       dvb_filter_ipack_reset(p);
+               }
+       }
+       if (buf[3] & ADAPT_FIELD) {  // adaptation field?
+               off = buf[4] + 1;
+               if (off+4 > 187) return;
+       }
+       dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p);
+}
+#endif
+
+#if 0
+/* needs 5 byte input, returns picture coding type*/
+static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr)
+{
+       u8 pct;
+
+       if (pr) printk( "Pic header: ");
+       pic->temporal_reference[field] = (( headr[0] << 2 ) |
+                                         (headr[1] & 0x03) )& 0x03ff;
+       if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
+
+       pct = ( headr[1] >> 2 ) & 0x07;
+       pic->picture_coding_type[field] = pct;
+       if (pr) {
+               switch(pct){
+                       case I_FRAME:
+                               printk( "  I-FRAME");
+                               break;
+                       case B_FRAME:
+                               printk( "  B-FRAME");
+                               break;
+                       case P_FRAME:
+                               printk( "  P-FRAME");
+                               break;
+               }
+       }
+
+
+       pic->vinfo.vbv_delay  = (( headr[1] >> 5 ) | ( headr[2] << 3) |
+                                ( (headr[3] & 0x1F) << 11) ) & 0xffff;
+
+       if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
+
+       pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
+               ((headr[4] & 0x80) >> 3);
+
+       if ( pct == B_FRAME ){
+               pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
+       }
+       if (pr) printk( " pic head param: 0x%x",
+                       pic->picture_header_parameter);
+
+       return pct;
+}
+#endif
+
+#if 0
+/* needs 4 byte input */
+static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr)
+{
+       if (pr) printk("GOP header: ");
+
+       pic->time_code  = (( headr[0] << 17 ) | ( headr[1] << 9) |
+                          ( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff;
+
+       if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F,
+                      ((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F),
+                      ((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F));
+
+       if ( ( headr[3] & 0x40 ) != 0 ){
+               pic->closed_gop = 1;
+       } else {
+               pic->closed_gop = 0;
+       }
+       if (pr) printk("closed: %d", pic->closed_gop);
+
+       if ( ( headr[3] & 0x20 ) != 0 ){
+               pic->broken_link = 1;
+       } else {
+               pic->broken_link = 0;
+       }
+       if (pr) printk(" broken: %d\n", pic->broken_link);
+
+       return 0;
+}
+#endif
+
+#if 0
+/* needs 8 byte input */
+static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr)
+{
+       int sw;
+       int form = -1;
+
+       if (pr) printk("Reading sequence header\n");
+
+       vi->horizontal_size     = ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
+       vi->vertical_size       = ((headr[1] &0x0F) << 8) | (headr[2]);
+
+       sw = (int)((headr[3]&0xF0) >> 4) ;
+
+       switch( sw ){
+       case 1:
+               if (pr)
+                       printk("Videostream: ASPECT: 1:1");
+               vi->aspect_ratio = 100;
+               break;
+       case 2:
+               if (pr)
+                       printk("Videostream: ASPECT: 4:3");
+               vi->aspect_ratio = 133;
+               break;
+       case 3:
+               if (pr)
+                       printk("Videostream: ASPECT: 16:9");
+               vi->aspect_ratio = 177;
+               break;
+       case 4:
+               if (pr)
+                       printk("Videostream: ASPECT: 2.21:1");
+               vi->aspect_ratio = 221;
+               break;
+
+       case 5 ... 15:
+               if (pr)
+                       printk("Videostream: ASPECT: reserved");
+               vi->aspect_ratio = 0;
+               break;
+
+       default:
+               vi->aspect_ratio = 0;
+               return -1;
+       }
+
+       if (pr)
+               printk("  Size = %dx%d",vi->horizontal_size,vi->vertical_size);
+
+       sw = (int)(headr[3]&0x0F);
+
+       switch ( sw ) {
+       case 1:
+               if (pr)
+                       printk("  FRate: 23.976 fps");
+               vi->framerate = 23976;
+               form = -1;
+               break;
+       case 2:
+               if (pr)
+                       printk("  FRate: 24 fps");
+               vi->framerate = 24000;
+               form = -1;
+               break;
+       case 3:
+               if (pr)
+                       printk("  FRate: 25 fps");
+               vi->framerate = 25000;
+               form = VIDEO_MODE_PAL;
+               break;
+       case 4:
+               if (pr)
+                       printk("  FRate: 29.97 fps");
+               vi->framerate = 29970;
+               form = VIDEO_MODE_NTSC;
+               break;
+       case 5:
+               if (pr)
+                       printk("  FRate: 30 fps");
+               vi->framerate = 30000;
+               form = VIDEO_MODE_NTSC;
+               break;
+       case 6:
+               if (pr)
+                       printk("  FRate: 50 fps");
+               vi->framerate = 50000;
+               form = VIDEO_MODE_PAL;
+               break;
+       case 7:
+               if (pr)
+                       printk("  FRate: 60 fps");
+               vi->framerate = 60000;
+               form = VIDEO_MODE_NTSC;
+               break;
+       }
+
+       vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
+
+       vi->vbv_buffer_size
+               = (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
+
+       if (pr){
+               printk("  BRate: %d Mbit/s",4*(vi->bit_rate)/10000);
+               printk("  vbvbuffer %d",16*1024*(vi->vbv_buffer_size));
+               printk("\n");
+       }
+
+       vi->video_format = form;
+
+       return 0;
+}
+#endif
+
+
+#if 0
+static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr)
+{
+       u8 *headr;
+       int found = 0;
+       int c = 0;
+
+       while (found < 4 && c+4 < count){
+               u8 *b;
+
+               b = mbuf+c;
+               if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
+                    && b[3] == 0xb3) found = 4;
+               else {
+                       c++;
+               }
+       }
+
+       if (! found) return -1;
+       c += 4;
+       if (c+12 >= count) return -1;
+       headr = mbuf+c;
+       if (read_sequence_header(headr, vi, pr) < 0) return -1;
+       vi->off = c-4;
+       return 0;
+}
+#endif
+
+
+#if 0
+static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
+{
+       u8 *headr;
+       int found = 0;
+       int c = 0;
+       int fr = 0;
+
+       while (found < 2 && c < count){
+               u8 b[2];
+               memcpy( b, mbuf+c, 2);
+
+               if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
+                       found = 2;
+               else {
+                       c++;
+               }
+       }
+
+       if (!found) return -1;
+
+       if (c+3 >= count) return -1;
+       headr = mbuf+c;
+
+       ai->layer = (headr[1] & 0x06) >> 1;
+
+       if (pr)
+               printk("Audiostream: Layer: %d", 4-ai->layer);
+
+
+       ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000;
+
+       if (pr){
+               if (ai->bit_rate == 0)
+                       printk("  Bit rate: free");
+               else if (ai->bit_rate == 0xf)
+                       printk("  BRate: reserved");
+               else
+                       printk("  BRate: %d kb/s", ai->bit_rate/1000);
+       }
+
+       fr = (headr[2] & 0x0c ) >> 2;
+       ai->frequency = freq[fr]*100;
+       if (pr){
+               if (ai->frequency == 3)
+                       printk("  Freq: reserved\n");
+               else
+                       printk("  Freq: %d kHz\n",ai->frequency);
+
+       }
+       ai->off = c;
+       return 0;
+}
+#endif
+
+
+int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
+{
+       u8 *headr;
+       int found = 0;
+       int c = 0;
+       u8 frame = 0;
+       int fr = 0;
+
+       while ( !found  && c < count){
+               u8 *b = mbuf+c;
+
+               if ( b[0] == 0x0b &&  b[1] == 0x77 )
+                       found = 1;
+               else {
+                       c++;
+               }
+       }
+
+       if (!found) return -1;
+       if (pr)
+               printk("Audiostream: AC3");
+
+       ai->off = c;
+       if (c+5 >= count) return -1;
+
+       ai->layer = 0;  // 0 for AC3
+       headr = mbuf+c+2;
+
+       frame = (headr[2]&0x3f);
+       ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
+
+       if (pr)
+               printk("  BRate: %d kb/s", (int) ai->bit_rate/1000);
+
+       ai->frequency = (headr[2] & 0xc0 ) >> 6;
+       fr = (headr[2] & 0xc0 ) >> 6;
+       ai->frequency = freq[fr]*100;
+       if (pr) printk ("  Freq: %d Hz\n", (int) ai->frequency);
+
+
+       ai->framesize = ac3_frames[fr][frame >> 1];
+       if ((frame & 1) &&  (fr == 1)) ai->framesize++;
+       ai->framesize = ai->framesize << 1;
+       if (pr) printk ("  Framesize %d\n",(int) ai->framesize);
+
+
+       return 0;
+}
+EXPORT_SYMBOL(dvb_filter_get_ac3info);
+
+
+#if 0
+static u8 *skip_pes_header(u8 **bufp)
+{
+       u8 *inbuf = *bufp;
+       u8 *buf = inbuf;
+       u8 *pts = NULL;
+       int skip = 0;
+
+       static const int mpeg1_skip_table[16] = {
+               1, 0xffff,      5,     10, 0xffff, 0xffff, 0xffff, 0xffff,
+               0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
+       };
+
+
+       if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
+               if (buf[7] & PTS_ONLY)
+                       pts = buf+9;
+               else pts = NULL;
+               buf = inbuf + 9 + inbuf[8];
+       } else {        /* mpeg1 */
+               for (buf = inbuf + 6; *buf == 0xff; buf++)
+                       if (buf == inbuf + 6 + 16) {
+                               break;
+                       }
+               if ((*buf & 0xc0) == 0x40)
+                       buf += 2;
+               skip = mpeg1_skip_table [*buf >> 4];
+               if (skip == 5 || skip == 10) pts = buf;
+               else pts = NULL;
+
+               buf += mpeg1_skip_table [*buf >> 4];
+       }
+
+       *bufp = buf;
+       return pts;
+}
+#endif
+
+#if 0
+static void initialize_quant_matrix( u32 *matrix )
+{
+       int i;
+
+       matrix[0]  = 0x08101013;
+       matrix[1]  = 0x10131616;
+       matrix[2]  = 0x16161616;
+       matrix[3]  = 0x1a181a1b;
+       matrix[4]  = 0x1b1b1a1a;
+       matrix[5]  = 0x1a1a1b1b;
+       matrix[6]  = 0x1b1d1d1d;
+       matrix[7]  = 0x2222221d;
+       matrix[8]  = 0x1d1d1b1b;
+       matrix[9]  = 0x1d1d2020;
+       matrix[10] = 0x22222526;
+       matrix[11] = 0x25232322;
+       matrix[12] = 0x23262628;
+       matrix[13] = 0x28283030;
+       matrix[14] = 0x2e2e3838;
+       matrix[15] = 0x3a454553;
+
+       for ( i = 16 ; i < 32 ; i++ )
+               matrix[i] = 0x10101010;
+}
+#endif
+
+#if 0
+static void initialize_mpg_picture(struct mpg_picture *pic)
+{
+       int i;
+
+       /* set MPEG1 */
+       pic->mpeg1_flag = 1;
+       pic->profile_and_level = 0x4A ;        /* MP@LL */
+       pic->progressive_sequence = 1;
+       pic->low_delay = 0;
+
+       pic->sequence_display_extension_flag = 0;
+       for ( i = 0 ; i < 4 ; i++ ){
+               pic->frame_centre_horizontal_offset[i] = 0;
+               pic->frame_centre_vertical_offset[i] = 0;
+       }
+       pic->last_frame_centre_horizontal_offset = 0;
+       pic->last_frame_centre_vertical_offset = 0;
+
+       pic->picture_display_extension_flag[0] = 0;
+       pic->picture_display_extension_flag[1] = 0;
+       pic->sequence_header_flag = 0;
+       pic->gop_flag = 0;
+       pic->sequence_end_flag = 0;
+}
+#endif
+
+#if 0
+static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic )
+{
+       int16_t last_h_offset;
+       int16_t last_v_offset;
+
+       int16_t *p_h_offset;
+       int16_t *p_v_offset;
+
+       if ( pic->mpeg1_flag ){
+               pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE;
+               pic->top_field_first = 0;
+               pic->repeat_first_field = 0;
+               pic->progressive_frame = 1;
+               pic->picture_coding_parameter = 0x000010;
+       }
+
+       /* Reset flag */
+       pic->picture_display_extension_flag[field_type] = 0;
+
+       last_h_offset = pic->last_frame_centre_horizontal_offset;
+       last_v_offset = pic->last_frame_centre_vertical_offset;
+       if ( field_type == FIRST_FIELD ){
+               p_h_offset = pic->frame_centre_horizontal_offset;
+               p_v_offset = pic->frame_centre_vertical_offset;
+               *p_h_offset = last_h_offset;
+               *(p_h_offset + 1) = last_h_offset;
+               *(p_h_offset + 2) = last_h_offset;
+               *p_v_offset = last_v_offset;
+               *(p_v_offset + 1) = last_v_offset;
+               *(p_v_offset + 2) = last_v_offset;
+       } else {
+               pic->frame_centre_horizontal_offset[3] = last_h_offset;
+               pic->frame_centre_vertical_offset[3] = last_v_offset;
+       }
+}
+#endif
+
+#if 0
+static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type)
+{
+       pic->picture_header = 0;
+       pic->sequence_header_data
+               = ( INIT_HORIZONTAL_SIZE << 20 )
+                       | ( INIT_VERTICAL_SIZE << 8 )
+                       | ( INIT_ASPECT_RATIO << 4 )
+                       | ( INIT_FRAME_RATE );
+       pic->mpeg1_flag = 0;
+       pic->vinfo.horizontal_size
+               = INIT_DISP_HORIZONTAL_SIZE;
+       pic->vinfo.vertical_size
+               = INIT_DISP_VERTICAL_SIZE;
+       pic->picture_display_extension_flag[field_type]
+               = 0;
+       pic->pts_flag[field_type] = 0;
+
+       pic->sequence_gop_header = 0;
+       pic->picture_header = 0;
+       pic->sequence_header_flag = 0;
+       pic->gop_flag = 0;
+       pic->sequence_end_flag = 0;
+       pic->sequence_display_extension_flag = 0;
+       pic->last_frame_centre_horizontal_offset = 0;
+       pic->last_frame_centre_vertical_offset = 0;
+       pic->channel = chan;
+}
+#endif
+
+void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
+                           dvb_filter_pes2ts_cb_t *cb, void *priv)
+{
+       unsigned char *buf=p2ts->buf;
+
+       buf[0]=0x47;
+       buf[1]=(pid>>8);
+       buf[2]=pid&0xff;
+       p2ts->cc=0;
+       p2ts->cb=cb;
+       p2ts->priv=priv;
+}
+EXPORT_SYMBOL(dvb_filter_pes2ts_init);
+
+int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
+                     int len, int payload_start)
+{
+       unsigned char *buf=p2ts->buf;
+       int ret=0, rest;
+
+       //len=6+((pes[4]<<8)|pes[5]);
+
+       if (payload_start)
+               buf[1]|=0x40;
+       else
+               buf[1]&=~0x40;
+       while (len>=184) {
+               buf[3]=0x10|((p2ts->cc++)&0x0f);
+               memcpy(buf+4, pes, 184);
+               if ((ret=p2ts->cb(p2ts->priv, buf)))
+                       return ret;
+               len-=184; pes+=184;
+               buf[1]&=~0x40;
+       }
+       if (!len)
+               return 0;
+       buf[3]=0x30|((p2ts->cc++)&0x0f);
+       rest=183-len;
+       if (rest) {
+               buf[5]=0x00;
+               if (rest-1)
+                       memset(buf+6, 0xff, rest-1);
+       }
+       buf[4]=rest;
+       memcpy(buf+5+rest, pes, len);
+       return p2ts->cb(p2ts->priv, buf);
+}
+EXPORT_SYMBOL(dvb_filter_pes2ts);