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 | 37 | #include "libavutil/imgutils.h" |
| 38 | 38 | #include "libavutil/intreadwrite.h" |
| 39 | 39 | #include "libavutil/bswap.h" |
| 40 | +#include "avdevice.h" | |
| 40 | 41 | } |
| 41 | 42 | |
| 42 | 43 | #include "decklink_common.h" |
| @@ -261,24 +262,100 @@ int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t directio · 218 unmodified lines | ||
| 261 | 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 | 269 | IDeckLink *dl = NULL; |
| 267 | 270 | IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance(); |
| 271 | + int ret = 0; | |
| 272 | + | |
| 268 | 273 | if (!iter) { |
| 269 | 274 | av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n"); |
| 270 | 275 | return AVERROR(EIO); |
| 271 | 276 | } |
| 272 | − av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink devices:\n"); | |
| 273 | − while (iter->Next(&dl) == S_OK) { | |
| 277 | + | |
| 278 | + while (ret == 0 && iter->Next(&dl) == S_OK) { | |
| 279 | + IDeckLinkOutput *output_config; | |
| 280 | + IDeckLinkInput *input_config; | |
| 274 | 281 | const char *displayName; |
| 282 | + AVDeviceInfo *new_device = NULL; | |
| 283 | + int add = 0; | |
| 284 | + | |
| 275 | 285 | ff_decklink_get_display_name(dl, &displayName); |
| 276 | − av_log(avctx, AV_LOG_INFO, "\t'%s'\n", displayName); | |
| 277 | − av_free((void *) displayName); | |
| 286 | + | |
| 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 | 331 | dl->Release(); |
| 279 | 332 | } |
| 280 | 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 | 361 | int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction) |