@ -72,8 +72,16 @@ static const int dv_aaux_packs_dist[12][9] = {
{ 0x50 , 0x51 , 0x52 , 0x53 , 0xff , 0xff , 0xff , 0xff , 0xff } ,
} ;
static int dv_audio_frame_size ( const AVDVProfile * sys , int frame )
static int dv_audio_frame_size ( const AVDVProfile * sys , int frame , int sample_rate )
{
if ( ( sys - > time_base . den = = 25 | | sys - > time_base . den = = 50 ) & & sys - > time_base . num = = 1 ) {
if ( sample_rate = = 32000 ) return 1280 ;
else if ( sample_rate = = 44100 ) return 1764 ;
else return 1920 ;
}
av_assert0 ( sample_rate = = 48000 ) ;
return sys - > audio_samples_dist [ frame % ( sizeof ( sys - > audio_samples_dist ) /
sizeof ( sys - > audio_samples_dist [ 0 ] ) ) ] ;
}
@ -84,6 +92,8 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu
time_t ct ;
uint32_t timecode ;
va_list ap ;
int audio_type = 0 ;
int channel ;
buf [ 0 ] = ( uint8_t ) pack_id ;
switch ( pack_id ) {
@ -94,10 +104,15 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu
break ;
case dv_audio_source : /* AAUX source pack */
va_start ( ap , buf ) ;
channel = va_arg ( ap , int ) ;
if ( c - > ast [ channel ] - > codec - > sample_rate = = 44100 ) {
audio_type = 1 ;
} else if ( c - > ast [ channel ] - > codec - > sample_rate = = 32000 )
audio_type = 2 ;
buf [ 1 ] = ( 1 < < 7 ) | /* locked mode -- SMPTE only supports locked mode */
( 1 < < 6 ) | /* reserved -- always 1 */
( dv_audio_frame_size ( c - > sys , c - > frames ) -
c - > sys - > audio_min_samples [ 0 ] ) ;
( dv_audio_frame_size ( c - > sys , c - > frames , c - > ast [ channel ] - > codec - > sample_rate ) -
c - > sys - > audio_min_samples [ audio_type ] ) ;
/* # of samples */
buf [ 2 ] = ( 0 < < 7 ) | /* multi-stereo */
( 0 < < 5 ) | /* #of audio channels per block: 0 -- 1 channel */
@ -109,8 +124,9 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu
( c - > sys - > n_difchan & 2 ) ; /* definition: 0 -- 25Mbps, 2 -- 50Mbps */
buf [ 4 ] = ( 1 < < 7 ) | /* emphasis: 1 -- off */
( 0 < < 6 ) | /* emphasis time constant: 0 -- reserved */
( 0 < < 3 ) | /* frequency: 0 -- 48kHz, 1 -- 44,1kHz, 2 -- 32kHz */
( audio_type < < 3 ) | /* frequency: 0 -- 48kHz, 1 -- 44,1kHz, 2 -- 32kHz */
0 ; /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */
va_end ( ap ) ;
break ;
case dv_audio_control :
@ -170,12 +186,12 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu
static void dv_inject_audio ( DVMuxContext * c , int channel , uint8_t * frame_ptr )
{
int i , j , d , of , size ;
size = 4 * dv_audio_frame_size ( c - > sys , c - > frames ) ;
size = 4 * dv_audio_frame_size ( c - > sys , c - > frames , c - > ast [ channel ] - > codec - > sample_rate ) ;
frame_ptr + = channel * c - > sys - > difseg_size * 150 * 80 ;
for ( i = 0 ; i < c - > sys - > difseg_size ; i + + ) {
frame_ptr + = 6 * 80 ; /* skip DIF segment header */
for ( j = 0 ; j < 9 ; j + + ) {
dv_write_pack ( dv_aaux_packs_dist [ i ] [ j ] , c , & frame_ptr [ 3 ] , i > = c - > sys - > difseg_size / 2 ) ;
dv_write_pack ( dv_aaux_packs_dist [ i ] [ j ] , c , & frame_ptr [ 3 ] , channel , i > = c - > sys - > difseg_size / 2 ) ;
for ( d = 8 ; d < 80 ; d + = 2 ) {
of = c - > sys - > audio_shuffle [ i ] [ j ] + ( d - 8 ) / 2 * c - > sys - > audio_stride ;
if ( of * 2 > = size )
@ -228,7 +244,6 @@ static int dv_assemble_frame(DVMuxContext *c, AVStream* st,
int i , reqasize ;
* frame = & c - > frame_buf [ 0 ] ;
reqasize = 4 * dv_audio_frame_size ( c - > sys , c - > frames ) ;
switch ( st - > codec - > codec_type ) {
case AVMEDIA_TYPE_VIDEO :
@ -247,6 +262,8 @@ static int dv_assemble_frame(DVMuxContext *c, AVStream* st,
av_log ( st - > codec , AV_LOG_ERROR , " Can't process DV frame #%d. Insufficient video data or severe sync problem. \n " , c - > frames ) ;
av_fifo_generic_write ( c - > audio_data [ i ] , data , data_size , NULL ) ;
reqasize = 4 * dv_audio_frame_size ( c - > sys , c - > frames , st - > codec - > sample_rate ) ;
/* Let us see if we've got enough audio for one DV frame. */
c - > has_audio | = ( ( reqasize < = av_fifo_size ( c - > audio_data [ i ] ) ) < < i ) ;
@ -261,6 +278,7 @@ static int dv_assemble_frame(DVMuxContext *c, AVStream* st,
c - > has_audio = 0 ;
for ( i = 0 ; i < c - > n_ast ; i + + ) {
dv_inject_audio ( c , i , * frame ) ;
reqasize = 4 * dv_audio_frame_size ( c - > sys , c - > frames , c - > ast [ i ] - > codec - > sample_rate ) ;
av_fifo_drain ( c - > audio_data [ i ] , reqasize ) ;
c - > has_audio | = ( ( reqasize < = av_fifo_size ( c - > audio_data [ i ] ) ) < < i ) ;
}
@ -309,15 +327,27 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s)
if ( ! vst | | vst - > codec - > codec_id ! = AV_CODEC_ID_DVVIDEO )
goto bail_out ;
for ( i = 0 ; i < c - > n_ast ; i + + ) {
if ( c - > ast [ i ] & & ( c - > ast [ i ] - > codec - > codec_id ! = AV_CODEC_ID_PCM_S16LE | |
c - > ast [ i ] - > codec - > sample_rate ! = 48000 | |
c - > ast [ i ] - > codec - > channels ! = 2 ) )
goto bail_out ;
if ( c - > ast [ i ] ) {
if ( c - > ast [ i ] - > codec - > codec_id ! = AV_CODEC_ID_PCM_S16LE | |
c - > ast [ i ] - > codec - > channels ! = 2 )
goto bail_out ;
if ( c - > ast [ i ] - > codec - > sample_rate ! = 48000 & &
c - > ast [ i ] - > codec - > sample_rate ! = 44100 & &
c - > ast [ i ] - > codec - > sample_rate ! = 32000 )
goto bail_out ;
}
}
c - > sys = av_dv_codec_profile ( vst - > codec - > width , vst - > codec - > height , vst - > codec - > pix_fmt ) ;
if ( ! c - > sys )
goto bail_out ;
if ( ( c - > sys - > time_base . den ! = 25 & & c - > sys - > time_base . den ! = 50 ) | | c - > sys - > time_base . num ! = 1 ) {
if ( c - > ast [ 0 ] & & c - > ast [ 0 ] - > codec - > sample_rate ! = 48000 )
goto bail_out ;
if ( c - > ast [ 1 ] & & c - > ast [ 1 ] - > codec - > sample_rate ! = 48000 )
goto bail_out ;
}
if ( ( c - > n_ast > 1 ) & & ( c - > sys - > n_difchan < 2 ) ) {
/* only 1 stereo pair is allowed in 25Mbps mode */
goto bail_out ;
@ -362,7 +392,7 @@ static int dv_write_header(AVFormatContext *s)
if ( ! dv_init_mux ( s ) ) {
av_log ( s , AV_LOG_ERROR , " Can't initialize DV format! \n "
" Make sure that you supply exactly two streams: \n "
" video: 25fps or 29.97fps, audio: 2ch/48kHz/PCM \n "
" video: 25fps or 29.97fps, audio: 2ch/48|44|32 kHz/PCM \n "
" (50Mbps allows an optional second audio stream) \n " ) ;
return - 1 ;
}