X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fsdi.cpp;h=84b3b4dad46614e86ef64071a3d7bf353c696146;hb=13f11c9667f8799c7c4939f7f1353d4eacb22a02;hp=b539074f6e3fad85d648cccad93909962f4956dc;hpb=e542ae5c523ad56dbc50df35a716914aa1d18f8e;p=vlc diff --git a/modules/access/sdi.cpp b/modules/access/sdi.cpp index b539074f6e..84b3b4dad4 100644 --- a/modules/access/sdi.cpp +++ b/modules/access/sdi.cpp @@ -25,6 +25,11 @@ static int Open ( vlc_object_t * ); static void Close( vlc_object_t * ); +#define CARD_INDEX_TEXT N_("Input card to use") +#define CARD_INDEX_LONGTEXT N_( \ + "SDI capture card to use, if multiple exist. " \ + "The cards are numbered from 0." ) + #define MODE_TEXT N_("Desired input video mode") #define MODE_LONGTEXT N_( \ "Desired input video mode for SDI captures. " \ @@ -52,6 +57,13 @@ static void Close( vlc_object_t * ); "Number of input audio channels for SDI captures. " \ "Must be 2, 8 or 16. 0 disables audio input." ) +#define VIDEO_CONNECTION_TEXT N_("Video connection") +#define VIDEO_CONNECTION_LONGTEXT N_( \ + "Video connection to use for SDI captures. " \ + "Valid choices: sdi, hdmi, opticalsdi, component, " \ + "composite, svideo. " \ + "Leave blank for card default." ) + #define ASPECT_RATIO_TEXT N_("Aspect ratio") #define ASPECT_RATIO_LONGTEXT N_( \ "Aspect ratio (4:3, 16:9). Default assumes square pixels." ) @@ -62,6 +74,8 @@ vlc_module_begin () set_category( CAT_INPUT ) set_subcategory( SUBCAT_INPUT_ACCESS ) + add_integer( "sdi-card-index", 0, NULL, + CARD_INDEX_TEXT, CARD_INDEX_LONGTEXT, true ) add_string( "sdi-mode", "pal ", NULL, MODE_TEXT, MODE_LONGTEXT, true ) add_integer( "sdi-caching", DEFAULT_PTS_DELAY / 1000, NULL, @@ -72,6 +86,8 @@ vlc_module_begin () RATE_TEXT, RATE_LONGTEXT, true ) add_integer( "sdi-audio-channels", 2, NULL, CHANNELS_TEXT, CHANNELS_LONGTEXT, true ) + add_string( "sdi-video-connection", 0, NULL, + VIDEO_CONNECTION_TEXT, VIDEO_CONNECTION_LONGTEXT, true ) add_string( "sdi-aspect-ratio", NULL, NULL, ASPECT_RATIO_TEXT, ASPECT_RATIO_LONGTEXT, true ) @@ -199,9 +215,17 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame { vlc_mutex_lock( &p_sys->frame_lock ); if( p_video_frame ) - p_sys->p_video_frame = p_video_frame; // FIXME: leak + { + if( p_sys->p_video_frame ) + block_Release( p_sys->p_video_frame ); + p_sys->p_video_frame = p_video_frame; + } if( p_audio_frame ) - p_sys->p_audio_frame = p_audio_frame; // FIXME: leak + { + if( p_sys->p_audio_frame ) + block_Release( p_sys->p_audio_frame ); + p_sys->p_audio_frame = p_audio_frame; + } vlc_cond_signal( &p_sys->has_frame ); vlc_mutex_unlock( &p_sys->frame_lock ); } @@ -236,22 +260,46 @@ static int Open( vlc_object_t *p_this ) if( !decklink_iterator ) { msg_Err( p_demux, "DeckLink drivers not found." ); - // FIXME: Leak here and several other error paths. + decklink_iterator->Release(); + Close( p_this ); return VLC_EGENERIC; } HRESULT result; - result = decklink_iterator->Next( &p_sys->p_card ); + int i_card_index = var_CreateGetInteger( p_demux, "sdi-card-index" ); + for( int i = 0; i <= i_card_index; ++i ) + { + result = decklink_iterator->Next( &p_sys->p_card ); + if( result != S_OK ) + break; + } + + decklink_iterator->Release(); + + if( result != S_OK ) + { + msg_Err( p_demux, "DeckLink PCI card %d not found", i_card_index ); + Close( p_this ); + return VLC_EGENERIC; + } + + const char *psz_model_name; + result = p_sys->p_card->GetModelName( &psz_model_name ); + if( result != S_OK ) { - msg_Err( p_demux, "No DeckLink PCI cards found" ); + msg_Err( p_demux, "Could not get model name" ); + Close( p_this ); return VLC_EGENERIC; } + msg_Dbg( p_demux, "Opened DeckLink PCI card %d (%s)", i_card_index, psz_model_name ); + if( p_sys->p_card->QueryInterface( IID_IDeckLinkInput, (void**)&p_sys->p_input) != S_OK ) { msg_Err( p_demux, "Card has no inputs" ); + Close( p_this ); return VLC_EGENERIC; } @@ -260,10 +308,49 @@ static int Open( vlc_object_t *p_this ) if( p_sys->p_card->QueryInterface( IID_IDeckLinkConfiguration, (void**)&p_config) != S_OK ) { msg_Err( p_demux, "Failed to get configuration interface" ); + Close( p_this ); return VLC_EGENERIC; } + + char *psz_tmp = var_CreateGetNonEmptyString( p_demux, "sdi-video-connection" ); + if( psz_tmp ) + { + BMDVideoConnection conn; + if ( !strcmp( psz_tmp, "sdi" ) ) + conn = bmdVideoConnectionSDI; + else if ( !strcmp( psz_tmp, "hdmi" ) ) + conn = bmdVideoConnectionHDMI; + else if ( !strcmp( psz_tmp, "opticalsdi" ) ) + conn = bmdVideoConnectionOpticalSDI; + else if ( !strcmp( psz_tmp, "component" ) ) + conn = bmdVideoConnectionComponent; + else if ( !strcmp( psz_tmp, "composite" ) ) + conn = bmdVideoConnectionComposite; + else if ( !strcmp( psz_tmp, "svideo" ) ) + conn = bmdVideoConnectionSVideo; + else + { + msg_Err( p_demux, "Invalid --sdi-video-connection specified; choose one of " \ + "sdi, hdmi, opticalsdi, component, composite, or svideo." ); + p_config->Release(); + free( psz_tmp ); + Close( p_this ); + return VLC_EGENERIC; + } + free( psz_tmp ); - char *psz_tmp = var_CreateGetNonEmptyString( p_demux, "sdi-audio-connection" ); + msg_Dbg( p_demux, "Setting video input format to 0x%x", conn); + result = p_config->SetVideoInputFormat( conn ); + if( result != S_OK ) + { + msg_Err( p_demux, "Failed to set video input connection" ); + p_config->Release(); + Close( p_this ); + return VLC_EGENERIC; + } + } + + psz_tmp = var_CreateGetNonEmptyString( p_demux, "sdi-audio-connection" ); if( psz_tmp ) { BMDAudioConnection conn; @@ -277,6 +364,7 @@ static int Open( vlc_object_t *p_this ) { msg_Err( p_demux, "Invalid --sdi-audio-connection specified; choose one of " \ "embedded, aesebu, or analog." ); + Close( p_this ); return VLC_EGENERIC; } free( psz_tmp ); @@ -286,9 +374,13 @@ static int Open( vlc_object_t *p_this ) if( result != S_OK ) { msg_Err( p_demux, "Failed to set audio input connection" ); + p_config->Release(); + Close( p_this ); return VLC_EGENERIC; } - } + } + + p_config->Release(); // Get the list of display modes. IDeckLinkDisplayModeIterator *p_display_iterator; @@ -296,24 +388,28 @@ static int Open( vlc_object_t *p_this ) if( result != S_OK ) { msg_Err( p_demux, "Failed to enumerate display modes" ); + p_display_iterator->Release(); + Close( p_this ); return VLC_EGENERIC; } - char *mode_string = var_CreateGetString( p_demux, "sdi-mode" ); - if( !mode_string || strlen( mode_string ) == 0 || strlen( mode_string ) > 4 ) { + char *psz_display_mode = var_CreateGetString( p_demux, "sdi-mode" ); + if( !psz_display_mode || strlen( psz_display_mode ) == 0 || strlen( psz_display_mode ) > 4 ) { msg_Err( p_demux, "Missing or invalid --sdi-mode string" ); + p_display_iterator->Release(); + Close( p_this ); return VLC_EGENERIC; } // Pad the --sdi-mode string to four characters, so the user can specify e.g. "pal" // without having to add the trailing space. - char mode_string_padded[5]; - strcpy(mode_string_padded, " "); - for( int i = 0; i < strlen(mode_string); ++i ) - mode_string_padded[i] = mode_string[i]; + char sz_display_mode_padded[5]; + strcpy(sz_display_mode_padded, " "); + for( int i = 0; i < strlen( psz_display_mode ); ++i ) + sz_display_mode_padded[i] = psz_display_mode[i]; BMDDisplayMode wanted_mode_id; - memcpy( &wanted_mode_id, &mode_string_padded, sizeof(wanted_mode_id) ); + memcpy( &wanted_mode_id, &sz_display_mode_padded, sizeof(wanted_mode_id) ); bool b_found_mode = false; @@ -326,15 +422,17 @@ static int Open( vlc_object_t *p_this ) break; } - char mode_id_text[5] = {0}; + char sz_mode_id_text[5] = {0}; BMDDisplayMode mode_id = ntohl( p_display_mode->GetDisplayMode() ); - memcpy( mode_id_text, &mode_id, sizeof(mode_id) ); + memcpy( sz_mode_id_text, &mode_id, sizeof(mode_id) ); - const char *mode_name; - result = p_display_mode->GetName( &mode_name ); + const char *psz_mode_name; + result = p_display_mode->GetName( &psz_mode_name ); if( result != S_OK ) { msg_Err( p_demux, "Failed to get display mode name" ); + p_display_iterator->Release(); + Close( p_this ); return VLC_EGENERIC; } @@ -343,37 +441,39 @@ static int Open( vlc_object_t *p_this ) if( result != S_OK ) { msg_Err( p_demux, "Failed to get frame rate" ); + p_display_iterator->Release(); + Close( p_this ); return VLC_EGENERIC; } - const char *field_dominance; + const char *psz_field_dominance; uint32_t i_dominance_flags = 0; switch( p_display_mode->GetFieldDominance() ) { case bmdProgressiveFrame: - field_dominance = ""; + psz_field_dominance = ""; break; case bmdProgressiveSegmentedFrame: - field_dominance = ", segmented"; + psz_field_dominance = ", segmented"; break; case bmdLowerFieldFirst: - field_dominance = ", interlaced [BFF]"; + psz_field_dominance = ", interlaced [BFF]"; i_dominance_flags = BLOCK_FLAG_BOTTOM_FIELD_FIRST; break; case bmdUpperFieldFirst: - field_dominance = ", interlaced [TFF]"; + psz_field_dominance = ", interlaced [TFF]"; i_dominance_flags = BLOCK_FLAG_TOP_FIELD_FIRST; break; case bmdUnknownFieldDominance: default: - field_dominance = ", unknown field dominance"; + psz_field_dominance = ", unknown field dominance"; break; } msg_Dbg( p_demux, "Found mode '%s': %s (%dx%d, %.3f fps%s)", - mode_id_text, mode_name, + sz_mode_id_text, psz_mode_name, p_display_mode->GetWidth(), p_display_mode->GetHeight(), - double(time_scale) / frame_duration, field_dominance ); + double(time_scale) / frame_duration, psz_field_dominance ); if( wanted_mode_id == mode_id ) { @@ -386,11 +486,14 @@ static int Open( vlc_object_t *p_this ) } } + p_display_iterator->Release(); + if( !b_found_mode ) { msg_Err( p_demux, "Unknown SDI mode specified. " \ "Run VLC with -v --verbose-objects=-all,+sdi " \ "to get a list of supported modes." ); + Close( p_this ); return VLC_EGENERIC; } @@ -398,6 +501,7 @@ static int Open( vlc_object_t *p_this ) if( result != S_OK ) { msg_Err( p_demux, "Failed to enable video input" ); + Close( p_this ); return VLC_EGENERIC; } @@ -410,6 +514,7 @@ static int Open( vlc_object_t *p_this ) if( result != S_OK ) { msg_Err( p_demux, "Failed to enable audio input" ); + Close( p_this ); return VLC_EGENERIC; } } @@ -421,6 +526,7 @@ static int Open( vlc_object_t *p_this ) if( result != S_OK ) { msg_Err( p_demux, "Failed to start streams" ); + Close( p_this ); return VLC_EGENERIC; } @@ -433,7 +539,7 @@ static int Open( vlc_object_t *p_this ) video_fmt.video.i_sar_den = 1; video_fmt.video.i_frame_rate = p_sys->i_fps_num; video_fmt.video.i_frame_rate_base = p_sys->i_fps_den; - video_fmt.i_bitrate = video_fmt.video.i_width * video_fmt.video.i_height * video_fmt.video.i_frame_rate * 2; + video_fmt.i_bitrate = video_fmt.video.i_width * video_fmt.video.i_height * video_fmt.video.i_frame_rate * 2 * 8; psz_tmp = var_CreateGetNonEmptyString( p_demux, "sdi-aspect-ratio" ); if( psz_tmp ) @@ -477,6 +583,16 @@ static void Close( vlc_object_t *p_this ) demux_t *p_demux = (demux_t *)p_this; demux_sys_t *p_sys = p_demux->p_sys; + if( p_sys->p_input ) + { + p_sys->p_input->StopStreams(); + p_sys->p_input->Release(); + } + + if( p_sys->p_card ) + p_sys->p_card->Release(); + + delete p_sys->p_delegate; free( p_sys ); }