@ -63,7 +63,8 @@ const char *http_state[] = {
" WAIT_FEED " ,
} ;
# define IOBUFFER_MAX_SIZE 16384
# define IOBUFFER_MAX_SIZE 32768
# define PACKET_MAX_SIZE 16384
/* coef for exponential mean for bitrate estimation in statistics */
# define AVG_COEF 0.9
@ -79,7 +80,6 @@ typedef struct HTTPContext {
struct sockaddr_in from_addr ; /* origin */
struct pollfd * poll_entry ; /* used when polling */
long timeout ;
UINT8 buffer [ IOBUFFER_MAX_SIZE ] ;
UINT8 * buffer_ptr , * buffer_end ;
int http_error ;
struct HTTPContext * next ;
@ -93,6 +93,8 @@ typedef struct HTTPContext {
struct FFStream * stream ;
AVFormatContext fmt_ctx ;
int last_packet_sent ; /* true if last data packet was sent */
UINT8 buffer [ IOBUFFER_MAX_SIZE ] ;
UINT8 pbuffer [ PACKET_MAX_SIZE ] ;
} HTTPContext ;
/* each generated stream is described here */
@ -528,13 +530,14 @@ static int http_parse_request(HTTPContext *c)
mime_type = c - > stream - > fmt - > mime_type ;
if ( ! mime_type )
mime_type = " application/x-octet_stream " ;
q + = sprintf ( q , " Content-type: %s \r \n " , mime_type ) ;
q + = sprintf ( q , " Pragma: no-cache \r \n " ) ;
/* for asf, we need extra headers */
if ( ! strcmp ( c - > stream - > fmt - > name , " asf " ) ) {
q + = sprintf ( q , " Pragma: features=broadcast \r \n " ) ;
q + = sprintf ( q , " Server: Cougar 4.1.0.3923 \r \n Cache-Control: no-cache \r \n Pragma: client-id=1234 \r \n Pragma: features= \" broadcast \" \r \n " ) ;
mime_type = " application/octet-stream " ;
}
q + = sprintf ( q , " Content-Type: %s \r \n " , mime_type ) ;
q + = sprintf ( q , " \r \n " ) ;
/* prepare output buffer */
@ -606,6 +609,8 @@ static void compute_stats(HTTPContext *c)
case CODEC_TYPE_VIDEO :
video_bit_rate + = st - > codec . bit_rate ;
break ;
default :
abort ( ) ;
}
}
q + = sprintf ( q , " <TD> %s <TD> %d <TD> %d <TD> %d " ,
@ -696,11 +701,15 @@ static void http_write_packet(void *opaque,
unsigned char * buf , int size )
{
HTTPContext * c = opaque ;
if ( size > IOBUFFER_MAX_SIZE )
if ( c - > buffer_ptr = = c - > buffer_end | | ! c - > buffer_ptr )
c - > buffer_ptr = c - > buffer_end = c - > buffer ;
if ( c - > buffer_end - c - > buffer + size > IOBUFFER_MAX_SIZE )
abort ( ) ;
memcpy ( c - > buffer , buf , size ) ;
c - > buffer_ptr = c - > buffer ;
c - > buffer_end = c - > buffer + size ;
memcpy ( c - > buffer_end , buf , size ) ;
c - > buffer_end + = size ;
}
static int open_input_stream ( HTTPContext * c , const char * info )
@ -718,6 +727,9 @@ static int open_input_stream(HTTPContext *c, const char *info)
/* compute position (absolute time) */
if ( find_info_tag ( buf , sizeof ( buf ) , " date " , info ) ) {
stream_pos = parse_date ( buf , 0 ) ;
} else if ( find_info_tag ( buf , sizeof ( buf ) , " buffer " , info ) ) {
int prebuffer = strtol ( buf , 0 , 10 ) ;
stream_pos = gettime ( ) - prebuffer * 1000000 ;
} else {
stream_pos = gettime ( ) ;
}
@ -763,7 +775,11 @@ static int http_prepare_data(HTTPContext *c)
AVStream * st ;
st = av_mallocz ( sizeof ( AVStream ) ) ;
c - > fmt_ctx . streams [ i ] = st ;
memcpy ( st , c - > stream - > streams [ i ] , sizeof ( AVStream ) ) ;
if ( c - > stream - > feed = = c - > stream )
memcpy ( st , c - > stream - > streams [ i ] , sizeof ( AVStream ) ) ;
else
memcpy ( st , c - > stream - > feed - > streams [ c - > stream - > feed_streams [ i ] ] , sizeof ( AVStream ) ) ;
st - > codec . frame_number = 0 ; /* XXX: should be done in
AVStream , not in codec */
c - > got_key_frame [ i ] = 0 ;
@ -782,7 +798,7 @@ static int http_prepare_data(HTTPContext *c)
c - > got_key_frame [ i ] = 0 ;
}
}
init_put_byte ( & c - > fmt_ctx . pb , c - > buffer , IOBUFFER _MAX_SIZE,
init_put_byte ( & c - > fmt_ctx . pb , c - > p buffer, PACKET _MAX_SIZE,
1 , c , NULL , http_write_packet , NULL ) ;
c - > fmt_ctx . pb . is_streamed = 1 ;
/* prepare header */
@ -881,9 +897,24 @@ static int http_prepare_data(HTTPContext *c)
}
}
} else {
send_it :
AVCodecContext * codec ;
send_it :
/* Fudge here */
codec = & c - > fmt_ctx . streams [ pkt . stream_index ] - > codec ;
codec - > key_frame = ( ( pkt . flags & PKT_FLAG_KEY ) ! = 0 ) ;
# ifdef PJSG
if ( codec - > codec_type = = CODEC_TYPE_AUDIO ) {
codec - > frame_size = ( codec - > sample_rate * pkt . duration + 500000 ) / 1000000 ;
/* printf("Calculated size %d, from sr %d, duration %d\n", codec->frame_size, codec->sample_rate, pkt.duration); */
}
# endif
if ( av_write_packet ( & c - > fmt_ctx , & pkt , 0 ) )
c - > state = HTTPSTATE_SEND_DATA_TRAILER ;
c - > state = HTTPSTATE_SEND_DATA_TRAILER ;
codec - > frame_number + + ;
}
av_free_packet ( & pkt ) ;
@ -920,15 +951,17 @@ static int http_send_data(HTTPContext *c)
}
}
len = write ( c - > fd , c - > buffer_ptr , c - > buffer_end - c - > buffer_ptr ) ;
if ( len < 0 ) {
if ( errno ! = EAGAIN & & errno ! = EINTR ) {
/* error : close connection */
return - 1 ;
if ( c - > buffer_end > c - > buffer_ptr ) {
len = write ( c - > fd , c - > buffer_ptr , c - > buffer_end - c - > buffer_ptr ) ;
if ( len < 0 ) {
if ( errno ! = EAGAIN & & errno ! = EINTR ) {
/* error : close connection */
return - 1 ;
}
} else {
c - > buffer_ptr + = len ;
c - > data_count + = len ;
}
} else {
c - > buffer_ptr + = len ;
c - > data_count + = len ;
}
return 0 ;
}
@ -963,10 +996,10 @@ static int http_receive_data(HTTPContext *c)
HTTPContext * c1 ;
if ( c - > buffer_ptr > = c - > buffer_end ) {
FFStream * feed = c - > stream ;
/* a packet has been received : write it in the store, except
if header */
if ( c - > data_count > FFM_PACKET_SIZE ) {
FFStream * feed = c - > stream ;
// printf("writing pos=0x%Lx size=0x%Lx\n", feed->feed_write_index, feed->feed_size);
/* XXX: use llseek or url_seek */
@ -992,6 +1025,29 @@ static int http_receive_data(HTTPContext *c)
c1 - > state = HTTPSTATE_SEND_DATA ;
}
}
} else {
/* We have a header in our hands that contains useful data */
AVFormatContext s ;
ByteIOContext * pb = & s . pb ;
int i ;
memset ( & s , 0 , sizeof ( s ) ) ;
url_open_buf ( pb , c - > buffer , c - > buffer_end - c - > buffer , URL_RDONLY ) ;
pb - > buf_end = c - > buffer_end ; /* ?? */
pb - > is_streamed = 1 ;
if ( feed - > fmt - > read_header ( & s , 0 ) < 0 ) {
goto fail ;
}
/* Now we have the actual streams */
if ( s . nb_streams ! = feed - > nb_streams ) {
goto fail ;
}
for ( i = 0 ; i < s . nb_streams ; i + + ) {
memcpy ( & feed - > streams [ i ] - > codec , & s . streams [ i ] - > codec , sizeof ( AVCodecContext ) ) ;
}
}
c - > buffer_ptr = c - > buffer ;
}
@ -1028,7 +1084,8 @@ int add_av_stream(FFStream *feed,
for ( i = 0 ; i < feed - > nb_streams ; i + + ) {
st = feed - > streams [ i ] ;
av1 = & st - > codec ;
if ( av1 - > codec = = av - > codec & &
if ( av1 - > codec_id = = av - > codec_id & &
av1 - > codec_type = = av - > codec_type & &
av1 - > bit_rate = = av - > bit_rate ) {
switch ( av - > codec_type ) {
@ -1044,6 +1101,8 @@ int add_av_stream(FFStream *feed,
av1 - > gop_size = = av - > gop_size )
goto found ;
break ;
default :
abort ( ) ;
}
}
}
@ -1187,6 +1246,8 @@ void add_codec(FFStream *stream, AVCodecContext *av)
av - > max_qdiff = 3 ;
break ;
default :
abort ( ) ;
}
st = av_mallocz ( sizeof ( AVStream ) ) ;
@ -1196,6 +1257,40 @@ void add_codec(FFStream *stream, AVCodecContext *av)
memcpy ( & st - > codec , av , sizeof ( AVCodecContext ) ) ;
}
int opt_audio_codec ( const char * arg )
{
AVCodec * p ;
p = first_avcodec ;
while ( p ) {
if ( ! strcmp ( p - > name , arg ) & & p - > type = = CODEC_TYPE_AUDIO )
break ;
p = p - > next ;
}
if ( p = = NULL ) {
return CODEC_ID_NONE ;
}
return p - > id ;
}
int opt_video_codec ( const char * arg )
{
AVCodec * p ;
p = first_avcodec ;
while ( p ) {
if ( ! strcmp ( p - > name , arg ) & & p - > type = = CODEC_TYPE_VIDEO )
break ;
p = p - > next ;
}
if ( p = = NULL ) {
return CODEC_ID_NONE ;
}
return p - > id ;
}
int parse_ffconfig ( const char * filename )
{
FILE * f ;
@ -1319,6 +1414,9 @@ int parse_ffconfig(const char *filename)
fprintf ( stderr , " %s:%d: No corresponding <Feed> for </Feed> \n " ,
filename , line_num ) ;
errors + + ;
} else {
/* Make sure that we start out clean */
unlink ( feed - > feed_filename ) ;
}
feed = NULL ;
} else if ( ! strcasecmp ( cmd , " <Stream " ) ) {
@ -1386,6 +1484,22 @@ int parse_ffconfig(const char *filename)
audio_id = stream - > fmt - > audio_codec ;
video_id = stream - > fmt - > video_codec ;
}
} else if ( ! strcasecmp ( cmd , " AudioCodec " ) ) {
get_arg ( arg , sizeof ( arg ) , & p ) ;
audio_id = opt_audio_codec ( arg ) ;
if ( audio_id = = CODEC_ID_NONE ) {
fprintf ( stderr , " %s:%d: Unknown AudioCodec: %s \n " ,
filename , line_num , arg ) ;
errors + + ;
}
} else if ( ! strcasecmp ( cmd , " VideoCodec " ) ) {
get_arg ( arg , sizeof ( arg ) , & p ) ;
video_id = opt_video_codec ( arg ) ;
if ( video_id = = CODEC_ID_NONE ) {
fprintf ( stderr , " %s:%d: Unknown VideoCodec: %s \n " ,
filename , line_num , arg ) ;
errors + + ;
}
} else if ( ! strcasecmp ( cmd , " AudioBitRate " ) ) {
get_arg ( arg , sizeof ( arg ) , & p ) ;
if ( stream ) {