From: Steinar Gunderson Date: Fri, 24 Sep 2010 19:42:28 +0000 (+0200) Subject: Add audio input support to the sdi driver. X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=930f5b0501954de09bb9b8e069e53f37566d76c7;p=vlc Add audio input support to the sdi driver. --- diff --git a/modules/access/sdi.cpp b/modules/access/sdi.cpp index 6ecdd0adcb..a2448d3f99 100644 --- a/modules/access/sdi.cpp +++ b/modules/access/sdi.cpp @@ -52,10 +52,12 @@ struct demux_sys_t IDeckLink *p_card; IDeckLinkInput *p_input; DeckLinkCaptureDelegate *p_delegate; - es_out_id_t *p_es; + es_out_id_t *p_video_es; + es_out_id_t *p_audio_es; vlc_mutex_t frame_lock; - block_t *p_frame; // protected by + block_t *p_video_frame; // protected by + block_t *p_audio_frame; // protected by vlc_cond_t has_frame; // related to }; @@ -85,6 +87,8 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFormatChanged(BMDVideoInputFormatChan HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame* videoFrame, IDeckLinkAudioInputPacket* audioFrame) { demux_sys_t *p_sys = p_demux_->p_sys; + block_t *p_video_frame = NULL; + block_t *p_audio_frame = NULL; if( videoFrame ) { @@ -99,11 +103,10 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame const int i_stride = videoFrame->GetRowBytes(); const int i_bpp = 2; - block_t *p_frame; - p_frame = block_New( p_demux_, i_width * i_height * i_bpp ); - if( !p_frame ) + p_video_frame = block_New( p_demux_, i_width * i_height * i_bpp ); + if( !p_video_frame ) { - msg_Err( p_demux_, "Could not allocate memory for frame" ); + msg_Err( p_demux_, "Could not allocate memory for video frame" ); return S_OK; } @@ -112,16 +115,42 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame for( int y = 0; y < i_height; ++y ) { const uint8_t *src = (const uint8_t *)frame_bytes + i_stride * y; - uint8_t *dst = (uint8_t *)p_frame->p_buffer + i_width * i_bpp * y; + uint8_t *dst = (uint8_t *)p_video_frame->p_buffer + i_width * i_bpp * y; memcpy( dst, src, i_width * i_bpp ); } BMDTimeValue stream_time, frame_duration; videoFrame->GetStreamTime( &stream_time, &frame_duration, CLOCK_FREQ ); - p_frame->i_pts = VLC_TS_0 + stream_time; + p_video_frame->i_pts = VLC_TS_0 + stream_time; + } + + if( audioFrame ) + { + const int i_bytes = audioFrame->GetSampleFrameCount() * sizeof(int16_t) * 2; + p_audio_frame = block_New( p_demux_, i_bytes ); + if( !p_audio_frame ) + { + msg_Err( p_demux_, "Could not allocate memory for audio frame" ); + return S_OK; + } + + void *frame_bytes; + audioFrame->GetBytes( &frame_bytes ); + memcpy( p_audio_frame->p_buffer, frame_bytes, i_bytes ); + + BMDTimeValue packet_time; + audioFrame->GetPacketTime( &packet_time, CLOCK_FREQ ); + p_audio_frame->i_pts = VLC_TS_0 + packet_time; + } + + if( p_video_frame || p_audio_frame ) + { vlc_mutex_lock( &p_sys->frame_lock ); - p_sys->p_frame = p_frame; // FIXME: leak + if( p_video_frame ) + p_sys->p_video_frame = p_video_frame; // FIXME: leak + if( p_audio_frame ) + p_sys->p_audio_frame = p_audio_frame; // FIXME: leak vlc_cond_signal( &p_sys->has_frame ); vlc_mutex_unlock( &p_sys->frame_lock ); } @@ -150,7 +179,7 @@ static int Open( vlc_object_t *p_this ) vlc_mutex_init( &p_sys->frame_lock ); vlc_cond_init( &p_sys->has_frame ); - p_sys->p_frame = NULL; + p_sys->p_video_frame = NULL; IDeckLinkIterator *decklink_iterator = CreateDeckLinkIteratorInstance(); if( !decklink_iterator ) @@ -175,17 +204,23 @@ static int Open( vlc_object_t *p_this ) return VLC_EGENERIC; } - p_sys->p_delegate = new DeckLinkCaptureDelegate( p_demux ); - p_sys->p_input->SetCallback( p_sys->p_delegate ); - result = p_sys->p_input->EnableVideoInput( bmdModePAL, bmdFormat8BitYUV, 0 ); if( result != S_OK ) { msg_Err( p_demux, "Failed to enable video input" ); return VLC_EGENERIC; } + + result = p_sys->p_input->EnableAudioInput( 48000, bmdAudioSampleType16bitInteger, 2 ); + if( result != S_OK ) + { + msg_Err( p_demux, "Failed to enable audio input" ); + return VLC_EGENERIC; + } + + p_sys->p_delegate = new DeckLinkCaptureDelegate( p_demux ); + p_sys->p_input->SetCallback( p_sys->p_delegate ); - // FIXME: add audio result = p_sys->p_input->StartStreams(); if( result != S_OK ) { @@ -193,19 +228,32 @@ static int Open( vlc_object_t *p_this ) return VLC_EGENERIC; } - /*eDeclare elementary streams */ - es_format_t fmt; - es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_UYVY ); - fmt.video.i_width = 720; - fmt.video.i_height = 576; - fmt.video.i_sar_num = 16 * fmt.video.i_height; - fmt.video.i_sar_den = 9 * fmt.video.i_width; - fmt.video.i_frame_rate = 25; - fmt.video.i_frame_rate_base = 1; + /* Declare elementary streams */ + es_format_t video_fmt; + es_format_Init( &video_fmt, VIDEO_ES, VLC_CODEC_UYVY ); + video_fmt.video.i_width = 720; + video_fmt.video.i_height = 576; + video_fmt.video.i_sar_num = 16 * video_fmt.video.i_height; + video_fmt.video.i_sar_den = 9 * video_fmt.video.i_width; + video_fmt.video.i_frame_rate = 25; + video_fmt.video.i_frame_rate_base = 1; + video_fmt.i_bitrate = video_fmt.video.i_width * video_fmt.video.i_height * video_fmt.video.i_frame_rate * 2; msg_Dbg( p_demux, "added new video es %4.4s %dx%d", - (char*)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height ); - p_sys->p_es = es_out_Add( p_demux->out, &fmt ); + (char*)&video_fmt.i_codec, video_fmt.video.i_width, video_fmt.video.i_height ); + p_sys->p_video_es = es_out_Add( p_demux->out, &video_fmt ); + + es_format_t audio_fmt; + es_format_Init( &audio_fmt, AUDIO_ES, VLC_CODEC_S16N ); + audio_fmt.audio.i_channels = 2; + audio_fmt.audio.i_rate = 48000; + audio_fmt.audio.i_bitspersample = 16; + audio_fmt.audio.i_blockalign = audio_fmt.audio.i_channels * audio_fmt.audio.i_bitspersample / 8; + audio_fmt.i_bitrate = audio_fmt.audio.i_channels * audio_fmt.audio.i_rate * audio_fmt.audio.i_bitspersample; + + msg_Dbg( p_demux, "added new audio es %4.4s %dHz %dbpp %dch", + (char*)&audio_fmt.i_codec, audio_fmt.audio.i_rate, audio_fmt.audio.i_bitspersample, audio_fmt.audio.i_channels); + p_sys->p_audio_es = es_out_Add( p_demux->out, &audio_fmt ); /* Update default_pts to a suitable value for access */ var_Create( p_demux, "sdi-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); @@ -257,20 +305,33 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) static int Demux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; - block_t *p_block; + block_t *p_video_block = NULL; + block_t *p_audio_block = NULL; vlc_mutex_lock( &p_sys->frame_lock ); - while( !p_sys->p_frame ) + while( !p_sys->p_video_frame && !p_sys->p_audio_frame ) vlc_cond_wait( &p_sys->has_frame, &p_sys->frame_lock ); - p_block = p_sys->p_frame; - p_sys->p_frame = NULL; + p_video_block = p_sys->p_video_frame; + p_sys->p_video_frame = NULL; + + p_audio_block = p_sys->p_audio_frame; + p_sys->p_audio_frame = NULL; vlc_mutex_unlock( &p_sys->frame_lock ); - es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts ); - es_out_Send( p_demux->out, p_sys->p_es, p_block ); + if( p_video_block ) + { + es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_video_block->i_pts ); + es_out_Send( p_demux->out, p_sys->p_video_es, p_video_block ); + } + + if( p_audio_block ) + { + es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_audio_block->i_pts ); + es_out_Send( p_demux->out, p_sys->p_audio_es, p_audio_block ); + } return 1; }