Add support for enumerating the sources/sinks via the ffmpeg command line options, as opposed to having to create a real pipeline and use the "-list_devices" option which does exit() after dumping out the options. Note that this patch preserves the existing "-list_devices" option, but now shares common code for the actual enumeration. Updated to reflect feedback from Marton Balint <cus@passwd.hu>.
Showing the changes to libavdevice/decklink_common.cpp (1 of 8 files). Show all
Unified · Split
| @@ -37,6 +37,7 @@ extern "C" { · 36 unmodified lines | |||
| 37 | #include "libavutil/imgutils.h" | 37 | #include "libavutil/imgutils.h" |
| 38 | #include "libavutil/intreadwrite.h" | 38 | #include "libavutil/intreadwrite.h" |
| 39 | #include "libavutil/bswap.h" | 39 | #include "libavutil/bswap.h" |
| 40 | #include "avdevice.h" | ||
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | #include "decklink_common.h" | 43 | #include "decklink_common.h" |
| @@ -261,24 +262,100 @@ int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t directio · 218 unmodified lines | |||
| 261 | return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction, num); | 262 | return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction, num); |
| 262 | } | 263 | } |
| 263 | 264 | ||
| 264 | int ff_decklink_list_devices(AVFormatContext *avctx) | 265 | int ff_decklink_list_devices(AVFormatContext *avctx, |
| 266 | struct AVDeviceInfoList *device_list, | ||
| 267 | int show_inputs, int show_outputs) | ||
| 265 | { | 268 | { |
| 266 | IDeckLink *dl = NULL; | 269 | IDeckLink *dl = NULL; |
| 267 | IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance(); | 270 | IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance(); |
| 271 | int ret = 0; | ||
| 272 | |||
| 268 | if (!iter) { | 273 | if (!iter) { |
| 269 | av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n"); | 274 | av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n"); |
| 270 | return AVERROR(EIO); | 275 | return AVERROR(EIO); |
| 271 | } | 276 | } |
| 272 | av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink devices:\n"); | 277 | |
| 273 | while (iter->Next(&dl) == S_OK) { | 278 | while (ret == 0 && iter->Next(&dl) == S_OK) { |
| 279 | IDeckLinkOutput *output_config; | ||
| 280 | IDeckLinkInput *input_config; | ||
| 274 | const char *displayName; | 281 | const char *displayName; |
| 282 | AVDeviceInfo *new_device = NULL; | ||
| 283 | int add = 0; | ||
| 284 | |||
| 275 | ff_decklink_get_display_name(dl, &displayName); | 285 | ff_decklink_get_display_name(dl, &displayName); |
| 276 | av_log(avctx, AV_LOG_INFO, "\t'%s'\n", displayName); | 286 | |
| 277 | av_free((void *) displayName); | 287 | if (show_outputs) { |
| 288 | if (dl->QueryInterface(IID_IDeckLinkOutput, (void **)&output_config) == S_OK) { | ||
| 289 | output_config->Release(); | ||
| 290 | add = 1; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | if (show_inputs) { | ||
| 295 | if (dl->QueryInterface(IID_IDeckLinkInput, (void **)&input_config) == S_OK) { | ||
| 296 | input_config->Release(); | ||
| 297 | add = 1; | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | if (add == 1) { | ||
| 302 | new_device = (AVDeviceInfo *) av_mallocz(sizeof(AVDeviceInfo)); | ||
| 303 | if (!new_device) { | ||
| 304 | ret = AVERROR(ENOMEM); | ||
| 305 | goto next; | ||
| 306 | } | ||
| 307 | new_device->device_name = av_strdup(displayName); | ||
| 308 | if (!new_device->device_name) { | ||
| 309 | ret = AVERROR(ENOMEM); | ||
| 310 | goto next; | ||
| 311 | } | ||
| 312 | |||
| 313 | new_device->device_description = av_strdup(displayName); | ||
| 314 | if (!new_device->device_description) { | ||
| 315 | av_freep(&new_device->device_name); | ||
| 316 | ret = AVERROR(ENOMEM); | ||
| 317 | goto next; | ||
| 318 | } | ||
| 319 | |||
| 320 | if ((ret = av_dynarray_add_nofree(&device_list->devices, | ||
| 321 | &device_list->nb_devices, new_device)) < 0) { | ||
| 322 | av_freep(&new_device->device_name); | ||
| 323 | av_freep(&new_device->device_description); | ||
| 324 | av_freep(&new_device); | ||
| 325 | goto next; | ||
| 326 | } | ||
| 327 | } | ||
| 328 | |||
| 329 | next: | ||
| 330 | av_freep(&displayName); | ||
| 278 | dl->Release(); | 331 | dl->Release(); |
| 279 | } | 332 | } |
| 280 | iter->Release(); | 333 | iter->Release(); |
| 281 | return 0; | 334 | return ret; |
| 335 | } | ||
| 336 | |||
| 337 | /* This is a wrapper around the ff_decklink_list_devices() which dumps the | ||
| 338 | output to av_log() and exits (for backward compatibility with the | ||
| 339 | "-list_devices" argument). */ | ||
| 340 | void ff_decklink_list_devices_legacy(AVFormatContext *avctx, | ||
| 341 | int show_inputs, int show_outputs) | ||
| 342 | { | ||
| 343 | struct AVDeviceInfoList *device_list = NULL; | ||
| 344 | int ret; | ||
| 345 | |||
| 346 | device_list = (struct AVDeviceInfoList *) av_mallocz(sizeof(AVDeviceInfoList)); | ||
| 347 | if (!device_list) | ||
| 348 | return; | ||
| 349 | |||
| 350 | ret = ff_decklink_list_devices(avctx, device_list, show_inputs, show_outputs); | ||
| 351 | if (ret == 0) { | ||
| 352 | av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink %s devices:\n", | ||
| 353 | show_inputs ? "input" : "output"); | ||
| 354 | for (int i = 0; i < device_list->nb_devices; i++) { | ||
| 355 | av_log(avctx, AV_LOG_INFO, "\t'%s'\n", device_list->devices[i]->device_name); | ||
| 356 | } | ||
| 357 | } | ||
| 358 | avdevice_free_list_devices(&device_list); | ||
| 282 | } | 359 | } |
| 283 | 360 | ||
| 284 | int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction) | 361 | int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction) |