2005-04-17 02:20:36 +04:00
# include "dvb_filter.h"
# include "av7110_ipack.h"
# include <linux/string.h> /* for memcpy() */
# include <linux/vmalloc.h>
void av7110_ipack_reset ( struct ipack * p )
{
p - > found = 0 ;
p - > cid = 0 ;
p - > plength = 0 ;
p - > flag1 = 0 ;
p - > flag2 = 0 ;
p - > hlength = 0 ;
p - > mpeg = 0 ;
p - > check = 0 ;
p - > which = 0 ;
p - > done = 0 ;
p - > count = 0 ;
}
int av7110_ipack_init ( struct ipack * p , int size ,
void ( * func ) ( u8 * buf , int size , void * priv ) )
{
if ( ! ( p - > buf = vmalloc ( size * sizeof ( u8 ) ) ) ) {
2005-07-08 04:58:03 +04:00
printk ( KERN_WARNING " Couldn't allocate memory for ipack \n " ) ;
2005-04-17 02:20:36 +04:00
return - ENOMEM ;
}
p - > size = size ;
p - > func = func ;
p - > repack_subids = 0 ;
av7110_ipack_reset ( p ) ;
return 0 ;
}
void av7110_ipack_free ( struct ipack * p )
{
vfree ( p - > buf ) ;
}
static void send_ipack ( struct ipack * p )
{
int off ;
struct dvb_audio_info ai ;
int ac3_off = 0 ;
int streamid = 0 ;
int nframes = 0 ;
int f = 0 ;
switch ( p - > mpeg ) {
case 2 :
if ( p - > count < 10 )
return ;
p - > buf [ 3 ] = p - > cid ;
p - > buf [ 4 ] = ( u8 ) ( ( ( p - > count - 6 ) & 0xff00 ) > > 8 ) ;
p - > buf [ 5 ] = ( u8 ) ( ( p - > count - 6 ) & 0x00ff ) ;
if ( p - > repack_subids & & p - > cid = = PRIVATE_STREAM1 ) {
off = 9 + p - > buf [ 8 ] ;
streamid = p - > buf [ off ] ;
if ( ( streamid & 0xf8 ) = = 0x80 ) {
ai . off = 0 ;
ac3_off = ( ( p - > buf [ off + 2 ] < < 8 ) |
p - > buf [ off + 3 ] ) ;
if ( ac3_off < p - > count )
f = dvb_filter_get_ac3info ( p - > buf + off + 3 + ac3_off ,
p - > count - ac3_off , & ai , 0 ) ;
if ( ! f ) {
nframes = ( p - > count - off - 3 - ac3_off ) /
ai . framesize + 1 ;
p - > buf [ off + 2 ] = ( ac3_off > > 8 ) & 0xff ;
p - > buf [ off + 3 ] = ( ac3_off ) & 0xff ;
p - > buf [ off + 1 ] = nframes ;
ac3_off + = nframes * ai . framesize - p - > count ;
}
}
}
p - > func ( p - > buf , p - > count , p - > data ) ;
p - > buf [ 6 ] = 0x80 ;
p - > buf [ 7 ] = 0x00 ;
p - > buf [ 8 ] = 0x00 ;
p - > count = 9 ;
if ( p - > repack_subids & & p - > cid = = PRIVATE_STREAM1
& & ( streamid & 0xf8 ) = = 0x80 ) {
p - > count + = 4 ;
p - > buf [ 9 ] = streamid ;
p - > buf [ 10 ] = ( ac3_off > > 8 ) & 0xff ;
p - > buf [ 11 ] = ( ac3_off ) & 0xff ;
p - > buf [ 12 ] = 0 ;
}
break ;
case 1 :
if ( p - > count < 8 )
return ;
p - > buf [ 3 ] = p - > cid ;
p - > buf [ 4 ] = ( u8 ) ( ( ( p - > count - 6 ) & 0xff00 ) > > 8 ) ;
p - > buf [ 5 ] = ( u8 ) ( ( p - > count - 6 ) & 0x00ff ) ;
p - > func ( p - > buf , p - > count , p - > data ) ;
p - > buf [ 6 ] = 0x0f ;
p - > count = 7 ;
break ;
}
}
void av7110_ipack_flush ( struct ipack * p )
{
if ( p - > plength ! = MMAX_PLENGTH - 6 | | p - > found < = 6 )
return ;
p - > plength = p - > found - 6 ;
p - > found = 0 ;
send_ipack ( p ) ;
av7110_ipack_reset ( p ) ;
}
static void write_ipack ( struct ipack * p , const u8 * data , int count )
{
u8 headr [ 3 ] = { 0x00 , 0x00 , 0x01 } ;
if ( p - > count < 6 ) {
memcpy ( p - > buf , headr , 3 ) ;
p - > count = 6 ;
}
if ( p - > count + count < p - > size ) {
memcpy ( p - > buf + p - > count , data , count ) ;
p - > count + = count ;
} else {
int rest = p - > size - p - > count ;
memcpy ( p - > buf + p - > count , data , rest ) ;
p - > count + = rest ;
send_ipack ( p ) ;
if ( count - rest > 0 )
write_ipack ( p , data + rest , count - rest ) ;
}
}
int av7110_ipack_instant_repack ( const u8 * buf , int count , struct ipack * p )
{
int l ;
int c = 0 ;
while ( c < count & & ( p - > mpeg = = 0 | |
( p - > mpeg = = 1 & & p - > found < 7 ) | |
( p - > mpeg = = 2 & & p - > found < 9 ) )
& & ( p - > found < 5 | | ! p - > done ) ) {
switch ( p - > found ) {
case 0 :
case 1 :
if ( buf [ c ] = = 0x00 )
p - > found + + ;
else
p - > found = 0 ;
c + + ;
break ;
case 2 :
if ( buf [ c ] = = 0x01 )
p - > found + + ;
else if ( buf [ c ] = = 0 )
p - > found = 2 ;
else
p - > found = 0 ;
c + + ;
break ;
case 3 :
p - > cid = 0 ;
switch ( buf [ c ] ) {
case PROG_STREAM_MAP :
case PRIVATE_STREAM2 :
case PROG_STREAM_DIR :
case ECM_STREAM :
case EMM_STREAM :
case PADDING_STREAM :
case DSM_CC_STREAM :
case ISO13522_STREAM :
p - > done = 1 ;
/* fall through */
case PRIVATE_STREAM1 :
case VIDEO_STREAM_S . . . VIDEO_STREAM_E :
case AUDIO_STREAM_S . . . AUDIO_STREAM_E :
p - > found + + ;
p - > cid = buf [ c ] ;
c + + ;
break ;
default :
p - > found = 0 ;
break ;
}
break ;
case 4 :
if ( count - c > 1 ) {
p - > plen [ 0 ] = buf [ c ] ;
c + + ;
p - > plen [ 1 ] = buf [ c ] ;
c + + ;
p - > found + = 2 ;
p - > plength = ( p - > plen [ 0 ] < < 8 ) | p - > plen [ 1 ] ;
} else {
p - > plen [ 0 ] = buf [ c ] ;
p - > found + + ;
return count ;
}
break ;
case 5 :
p - > plen [ 1 ] = buf [ c ] ;
c + + ;
p - > found + + ;
p - > plength = ( p - > plen [ 0 ] < < 8 ) | p - > plen [ 1 ] ;
break ;
case 6 :
if ( ! p - > done ) {
p - > flag1 = buf [ c ] ;
c + + ;
p - > found + + ;
if ( ( p - > flag1 & 0xc0 ) = = 0x80 )
p - > mpeg = 2 ;
else {
p - > hlength = 0 ;
p - > which = 0 ;
p - > mpeg = 1 ;
p - > flag2 = 0 ;
}
}
break ;
case 7 :
if ( ! p - > done & & p - > mpeg = = 2 ) {
p - > flag2 = buf [ c ] ;
c + + ;
p - > found + + ;
}
break ;
case 8 :
if ( ! p - > done & & p - > mpeg = = 2 ) {
p - > hlength = buf [ c ] ;
c + + ;
p - > found + + ;
}
break ;
}
}
if ( c = = count )
return count ;
if ( ! p - > plength )
p - > plength = MMAX_PLENGTH - 6 ;
if ( p - > done | | ( ( p - > mpeg = = 2 & & p - > found > = 9 ) | |
( p - > mpeg = = 1 & & p - > found > = 7 ) ) ) {
switch ( p - > cid ) {
case AUDIO_STREAM_S . . . AUDIO_STREAM_E :
case VIDEO_STREAM_S . . . VIDEO_STREAM_E :
case PRIVATE_STREAM1 :
if ( p - > mpeg = = 2 & & p - > found = = 9 ) {
write_ipack ( p , & p - > flag1 , 1 ) ;
write_ipack ( p , & p - > flag2 , 1 ) ;
write_ipack ( p , & p - > hlength , 1 ) ;
}
if ( p - > mpeg = = 1 & & p - > found = = 7 )
write_ipack ( p , & p - > flag1 , 1 ) ;
if ( p - > mpeg = = 2 & & ( p - > flag2 & PTS_ONLY ) & &
p - > found < 14 ) {
while ( c < count & & p - > found < 14 ) {
p - > pts [ p - > found - 9 ] = buf [ c ] ;
write_ipack ( p , buf + c , 1 ) ;
c + + ;
p - > found + + ;
}
if ( c = = count )
return count ;
}
if ( p - > mpeg = = 1 & & p - > which < 2000 ) {
if ( p - > found = = 7 ) {
p - > check = p - > flag1 ;
p - > hlength = 1 ;
}
while ( ! p - > which & & c < count & &
p - > check = = 0xff ) {
p - > check = buf [ c ] ;
write_ipack ( p , buf + c , 1 ) ;
c + + ;
p - > found + + ;
p - > hlength + + ;
}
if ( c = = count )
return count ;
if ( ( p - > check & 0xc0 ) = = 0x40 & & ! p - > which ) {
p - > check = buf [ c ] ;
write_ipack ( p , buf + c , 1 ) ;
c + + ;
p - > found + + ;
p - > hlength + + ;
p - > which = 1 ;
if ( c = = count )
return count ;
p - > check = buf [ c ] ;
write_ipack ( p , buf + c , 1 ) ;
c + + ;
p - > found + + ;
p - > hlength + + ;
p - > which = 2 ;
if ( c = = count )
return count ;
}
if ( p - > which = = 1 ) {
p - > check = buf [ c ] ;
write_ipack ( p , buf + c , 1 ) ;
c + + ;
p - > found + + ;
p - > hlength + + ;
p - > which = 2 ;
if ( c = = count )
return count ;
}
if ( ( p - > check & 0x30 ) & & p - > check ! = 0xff ) {
p - > flag2 = ( p - > check & 0xf0 ) < < 2 ;
p - > pts [ 0 ] = p - > check ;
p - > which = 3 ;
}
if ( c = = count )
return count ;
if ( p - > which > 2 ) {
if ( ( p - > flag2 & PTS_DTS_FLAGS ) = = PTS_ONLY ) {
while ( c < count & & p - > which < 7 ) {
p - > pts [ p - > which - 2 ] = buf [ c ] ;
write_ipack ( p , buf + c , 1 ) ;
c + + ;
p - > found + + ;
p - > which + + ;
p - > hlength + + ;
}
if ( c = = count )
return count ;
} else if ( ( p - > flag2 & PTS_DTS_FLAGS ) = = PTS_DTS ) {
while ( c < count & & p - > which < 12 ) {
if ( p - > which < 7 )
p - > pts [ p - > which - 2 ] = buf [ c ] ;
write_ipack ( p , buf + c , 1 ) ;
c + + ;
p - > found + + ;
p - > which + + ;
p - > hlength + + ;
}
if ( c = = count )
return count ;
}
p - > which = 2000 ;
}
}
while ( c < count & & p - > found < p - > plength + 6 ) {
l = count - c ;
if ( l + p - > found > p - > plength + 6 )
l = p - > plength + 6 - p - > found ;
write_ipack ( p , buf + c , l ) ;
p - > found + = l ;
c + = l ;
}
break ;
}
if ( p - > done ) {
if ( p - > found + count - c < p - > plength + 6 ) {
p - > found + = count - c ;
c = count ;
} else {
c + = p - > plength + 6 - p - > found ;
p - > found = p - > plength + 6 ;
}
}
if ( p - > plength & & p - > found = = p - > plength + 6 ) {
send_ipack ( p ) ;
av7110_ipack_reset ( p ) ;
if ( c < count )
av7110_ipack_instant_repack ( buf + c , count - c , p ) ;
}
}
return count ;
}