@ -242,6 +242,9 @@ static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
static int rtp_new_av_stream ( HTTPContext * c ,
static int rtp_new_av_stream ( HTTPContext * c ,
int stream_index , struct sockaddr_in * dest_addr ,
int stream_index , struct sockaddr_in * dest_addr ,
HTTPContext * rtsp_c ) ;
HTTPContext * rtsp_c ) ;
/* utils */
static inline int check_codec_match ( AVCodecContext * ccf , AVCodecContext * ccs ,
int stream ) ;
static const char * my_program_name ;
static const char * my_program_name ;
@ -3624,11 +3627,46 @@ static void build_file_streams(void)
}
}
}
}
static inline
int check_codec_match ( AVCodecContext * ccf , AVCodecContext * ccs , int stream )
{
int matches = 1 ;
# define CHECK_CODEC(x) (ccf->x != ccs->x)
if ( CHECK_CODEC ( codec_id ) | | CHECK_CODEC ( codec_type ) ) {
http_log ( " Codecs do not match for stream %d \n " , stream ) ;
matches = 0 ;
} else if ( CHECK_CODEC ( bit_rate ) | | CHECK_CODEC ( flags ) ) {
http_log ( " Codec bitrates do not match for stream %d \n " , stream ) ;
matches = 0 ;
} else if ( ccf - > codec_type = = AVMEDIA_TYPE_VIDEO ) {
if ( CHECK_CODEC ( time_base . den ) | |
CHECK_CODEC ( time_base . num ) | |
CHECK_CODEC ( width ) | |
CHECK_CODEC ( height ) ) {
http_log ( " Codec width, height or framerate do not match for stream %d \n " , stream ) ;
matches = 0 ;
}
} else if ( ccf - > codec_type = = AVMEDIA_TYPE_AUDIO ) {
if ( CHECK_CODEC ( sample_rate ) | |
CHECK_CODEC ( channels ) | |
CHECK_CODEC ( frame_size ) ) {
http_log ( " Codec sample_rate, channels, frame_size do not match for stream %d \n " , stream ) ;
matches = 0 ;
}
} else {
http_log ( " Unknown codec type for stream %d \n " , stream ) ;
matches = 0 ;
}
return matches ;
}
/* compute the needed AVStream for each feed */
/* compute the needed AVStream for each feed */
static int build_feed_streams ( void )
static int build_feed_streams ( void )
{
{
FFServerStream * stream , * feed ;
FFServerStream * stream , * feed ;
int i ;
int i , fd ;
/* gather all streams */
/* gather all streams */
for ( stream = config . first_stream ; stream ; stream = stream - > next ) {
for ( stream = config . first_stream ; stream ; stream = stream - > next ) {
@ -3639,98 +3677,77 @@ static int build_feed_streams(void)
if ( stream - > is_feed ) {
if ( stream - > is_feed ) {
for ( i = 0 ; i < stream - > nb_streams ; i + + )
for ( i = 0 ; i < stream - > nb_streams ; i + + )
stream - > feed_streams [ i ] = i ;
stream - > feed_streams [ i ] = i ;
} else {
continue ;
/* we handle a stream coming from a feed */
for ( i = 0 ; i < stream - > nb_streams ; i + + )
stream - > feed_streams [ i ] = add_av_stream ( feed ,
stream - > streams [ i ] ) ;
}
}
/* we handle a stream coming from a feed */
for ( i = 0 ; i < stream - > nb_streams ; i + + )
stream - > feed_streams [ i ] = add_av_stream ( feed , stream - > streams [ i ] ) ;
}
}
/* create feed files if needed */
/* create feed files if needed */
for ( feed = config . first_feed ; feed ; feed = feed - > next_feed ) {
for ( feed = config . first_feed ; feed ; feed = feed - > next_feed ) {
int fd ;
if ( avio_check ( feed - > feed_filename , AVIO_FLAG_READ ) > 0 ) {
if ( avio_check ( feed - > feed_filename , AVIO_FLAG_READ ) > 0 ) {
/* See if it matches */
AVFormatContext * s = NULL ;
AVFormatContext * s = NULL ;
int matches = 0 ;
int matches = 0 ;
if ( avformat_open_input ( & s , feed - > feed_filename , NULL , NULL ) > = 0 ) {
/* See if it matches */
/* set buffer size */
int ret = ffio_set_buf_size ( s - > pb , FFM_PACKET_SIZE ) ;
if ( ret < 0 ) {
http_log ( " Failed to set buffer size \n " ) ;
goto bail ;
}
/* Now see if it matches */
if ( avformat_open_input ( & s , feed - > feed_filename , NULL , NULL ) < 0 ) {
if ( s - > nb_streams = = feed - > nb_streams ) {
http_log ( " Deleting feed file '%s' as it appears "
matches = 1 ;
" to be corrupt \n " ,
for ( i = 0 ; i < s - > nb_streams ; i + + ) {
feed - > feed_filename ) ;
AVStream * sf , * ss ;
goto drop ;
sf = feed - > streams [ i ] ;
}
ss = s - > streams [ i ] ;
if ( sf - > index ! = ss - > index | |
sf - > id ! = ss - > id ) {
http_log ( " Index & Id do not match for stream %d (%s) \n " ,
i , feed - > feed_filename ) ;
matches = 0 ;
} else {
AVCodecContext * ccf , * ccs ;
ccf = sf - > codec ;
ccs = ss - > codec ;
# define CHECK_CODEC(x) (ccf->x != ccs->x)
if ( CHECK_CODEC ( codec_id ) | | CHECK_CODEC ( codec_type ) ) {
/* set buffer size */
http_log ( " Codecs do not match for stream %d \n " , i ) ;
if ( ffio_set_buf_size ( s - > pb , FFM_PACKET_SIZE ) < 0 ) {
matches = 0 ;
http_log ( " Failed to set buffer size \n " ) ;
} else if ( CHECK_CODEC ( bit_rate ) | | CHECK_CODEC ( flags ) ) {
avformat_close_input ( & s ) ;
http_log ( " Codec bitrates do not match for stream %d \n " , i ) ;
goto bail ;
matches = 0 ;
}
} else if ( ccf - > codec_type = = AVMEDIA_TYPE_VIDEO ) {
if ( CHECK_CODEC ( time_base . den ) | |
/* Now see if it matches */
CHECK_CODEC ( time_base . num ) | |
if ( s - > nb_streams ! = feed - > nb_streams ) {
CHECK_CODEC ( width ) | |
http_log ( " Deleting feed file '%s' as stream counts "
CHECK_CODEC ( height ) ) {
" differ (%d != %d) \n " ,
http_log ( " Codec width, height and framerate do not match for stream %d \n " , i ) ;
feed - > feed_filename , s - > nb_streams , feed - > nb_streams ) ;
matches = 0 ;
goto drop ;
}
}
} else if ( ccf - > codec_type = = AVMEDIA_TYPE_AUDIO ) {
if ( CHECK_CODEC ( sample_rate ) | |
matches = 1 ;
CHECK_CODEC ( channels ) | |
for ( i = 0 ; i < s - > nb_streams ; i + + ) {
CHECK_CODEC ( frame_size ) ) {
AVStream * sf , * ss ;
http_log ( " Codec sample_rate, channels, frame_size do not match for stream %d \n " , i ) ;
matches = 0 ;
sf = feed - > streams [ i ] ;
}
ss = s - > streams [ i ] ;
} else {
http_log ( " Unknown codec type \n " ) ;
matches = 0 ;
}
}
if ( ! matches )
break ;
}
} else
http_log ( " Deleting feed file '%s' as stream counts differ (%d != %d) \n " ,
feed - > feed_filename , s - > nb_streams , feed - > nb_streams ) ;
if ( sf - > index ! = ss - > index | | sf - > id ! = ss - > id ) {
http_log ( " Index & Id do not match for stream %d (%s) \n " ,
i , feed - > feed_filename ) ;
matches = 0 ;
break ;
}
matches = check_codec_match ( sf - > codec , ss - > codec , i ) ;
if ( ! matches )
break ;
}
drop :
if ( s )
avformat_close_input ( & s ) ;
avformat_close_input ( & s ) ;
} else
http_log ( " Deleting feed file '%s' as it appears to be corrupt \n " ,
feed - > feed_filename ) ;
if ( ! matches ) {
if ( ! matches ) {
if ( feed - > readonly ) {
if ( feed - > readonly ) {
http_log ( " Unable to delete feed file '%s' as it is marked readonly \n " ,
http_log ( " Unable to delete read-only feed file '%s' \n " ,
feed - > feed_filename ) ;
feed - > feed_filename ) ;
goto bail ;
goto bail ;
}
}
unlink ( feed - > feed_filename ) ;
unlink ( feed - > feed_filename ) ;
}
}
}
}
if ( avio_check ( feed - > feed_filename , AVIO_FLAG_WRITE ) < = 0 ) {
if ( avio_check ( feed - > feed_filename , AVIO_FLAG_WRITE ) < = 0 ) {
AVFormatContext * s = avformat_alloc_context ( ) ;
AVFormatContext * s = avformat_alloc_context ( ) ;
@ -3740,8 +3757,10 @@ static int build_feed_streams(void)
}
}
if ( feed - > readonly ) {
if ( feed - > readonly ) {
http_log ( " Unable to create feed file '%s' as it is marked readonly \n " ,
http_log ( " Unable to create feed file '%s' as it is "
feed - > feed_filename ) ;
" marked readonly \n " ,
feed - > feed_filename ) ;
avformat_free_context ( s ) ;
goto bail ;
goto bail ;
}
}
@ -3749,6 +3768,7 @@ static int build_feed_streams(void)
if ( avio_open ( & s - > pb , feed - > feed_filename , AVIO_FLAG_WRITE ) < 0 ) {
if ( avio_open ( & s - > pb , feed - > feed_filename , AVIO_FLAG_WRITE ) < 0 ) {
http_log ( " Could not open output feed file '%s' \n " ,
http_log ( " Could not open output feed file '%s' \n " ,
feed - > feed_filename ) ;
feed - > feed_filename ) ;
avformat_free_context ( s ) ;
goto bail ;
goto bail ;
}
}
s - > oformat = feed - > fmt ;
s - > oformat = feed - > fmt ;
@ -3756,6 +3776,8 @@ static int build_feed_streams(void)
s - > streams = feed - > streams ;
s - > streams = feed - > streams ;
if ( avformat_write_header ( s , NULL ) < 0 ) {
if ( avformat_write_header ( s , NULL ) < 0 ) {
http_log ( " Container doesn't support the required parameters \n " ) ;
http_log ( " Container doesn't support the required parameters \n " ) ;
avio_closep ( & s - > pb ) ;
avformat_free_context ( s ) ;
goto bail ;
goto bail ;
}
}
/* XXX: need better API */
/* XXX: need better API */
@ -3765,6 +3787,7 @@ static int build_feed_streams(void)
s - > nb_streams = 0 ;
s - > nb_streams = 0 ;
avformat_free_context ( s ) ;
avformat_free_context ( s ) ;
}
}
/* get feed size and write index */
/* get feed size and write index */
fd = open ( feed - > feed_filename , O_RDONLY ) ;
fd = open ( feed - > feed_filename , O_RDONLY ) ;
if ( fd < 0 ) {
if ( fd < 0 ) {
@ -3773,7 +3796,8 @@ static int build_feed_streams(void)
goto bail ;
goto bail ;
}
}
feed - > feed_write_index = FFMAX ( ffm_read_write_index ( fd ) , FFM_PACKET_SIZE ) ;
feed - > feed_write_index = FFMAX ( ffm_read_write_index ( fd ) ,
FFM_PACKET_SIZE ) ;
feed - > feed_size = lseek ( fd , 0 , SEEK_END ) ;
feed - > feed_size = lseek ( fd , 0 , SEEK_END ) ;
/* ensure that we do not wrap before the end of file */
/* ensure that we do not wrap before the end of file */
if ( feed - > feed_max_size & & feed - > feed_max_size < feed - > feed_size )
if ( feed - > feed_max_size & & feed - > feed_max_size < feed - > feed_size )