mirror of
https://github.com/librempeg/librempeg
synced 2024-11-22 00:51:37 +00:00
libavdevice/decklink: add support for -sources and -sinks arguments
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>. Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com> Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
parent
ff6de6b180
commit
278588cd0b
@ -37,6 +37,7 @@ extern "C" {
|
|||||||
#include "libavutil/imgutils.h"
|
#include "libavutil/imgutils.h"
|
||||||
#include "libavutil/intreadwrite.h"
|
#include "libavutil/intreadwrite.h"
|
||||||
#include "libavutil/bswap.h"
|
#include "libavutil/bswap.h"
|
||||||
|
#include "avdevice.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "decklink_common.h"
|
#include "decklink_common.h"
|
||||||
@ -261,24 +262,100 @@ int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t directio
|
|||||||
return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction, num);
|
return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_decklink_list_devices(AVFormatContext *avctx)
|
int ff_decklink_list_devices(AVFormatContext *avctx,
|
||||||
|
struct AVDeviceInfoList *device_list,
|
||||||
|
int show_inputs, int show_outputs)
|
||||||
{
|
{
|
||||||
IDeckLink *dl = NULL;
|
IDeckLink *dl = NULL;
|
||||||
IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance();
|
IDeckLinkIterator *iter = CreateDeckLinkIteratorInstance();
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (!iter) {
|
if (!iter) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n");
|
av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator\n");
|
||||||
return AVERROR(EIO);
|
return AVERROR(EIO);
|
||||||
}
|
}
|
||||||
av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink devices:\n");
|
|
||||||
while (iter->Next(&dl) == S_OK) {
|
while (ret == 0 && iter->Next(&dl) == S_OK) {
|
||||||
|
IDeckLinkOutput *output_config;
|
||||||
|
IDeckLinkInput *input_config;
|
||||||
const char *displayName;
|
const char *displayName;
|
||||||
|
AVDeviceInfo *new_device = NULL;
|
||||||
|
int add = 0;
|
||||||
|
|
||||||
ff_decklink_get_display_name(dl, &displayName);
|
ff_decklink_get_display_name(dl, &displayName);
|
||||||
av_log(avctx, AV_LOG_INFO, "\t'%s'\n", displayName);
|
|
||||||
av_free((void *) displayName);
|
if (show_outputs) {
|
||||||
|
if (dl->QueryInterface(IID_IDeckLinkOutput, (void **)&output_config) == S_OK) {
|
||||||
|
output_config->Release();
|
||||||
|
add = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_inputs) {
|
||||||
|
if (dl->QueryInterface(IID_IDeckLinkInput, (void **)&input_config) == S_OK) {
|
||||||
|
input_config->Release();
|
||||||
|
add = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add == 1) {
|
||||||
|
new_device = (AVDeviceInfo *) av_mallocz(sizeof(AVDeviceInfo));
|
||||||
|
if (!new_device) {
|
||||||
|
ret = AVERROR(ENOMEM);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
new_device->device_name = av_strdup(displayName);
|
||||||
|
if (!new_device->device_name) {
|
||||||
|
ret = AVERROR(ENOMEM);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_device->device_description = av_strdup(displayName);
|
||||||
|
if (!new_device->device_description) {
|
||||||
|
av_freep(&new_device->device_name);
|
||||||
|
ret = AVERROR(ENOMEM);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = av_dynarray_add_nofree(&device_list->devices,
|
||||||
|
&device_list->nb_devices, new_device)) < 0) {
|
||||||
|
av_freep(&new_device->device_name);
|
||||||
|
av_freep(&new_device->device_description);
|
||||||
|
av_freep(&new_device);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
av_freep(&displayName);
|
||||||
dl->Release();
|
dl->Release();
|
||||||
}
|
}
|
||||||
iter->Release();
|
iter->Release();
|
||||||
return 0;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a wrapper around the ff_decklink_list_devices() which dumps the
|
||||||
|
output to av_log() and exits (for backward compatibility with the
|
||||||
|
"-list_devices" argument). */
|
||||||
|
void ff_decklink_list_devices_legacy(AVFormatContext *avctx,
|
||||||
|
int show_inputs, int show_outputs)
|
||||||
|
{
|
||||||
|
struct AVDeviceInfoList *device_list = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
device_list = (struct AVDeviceInfoList *) av_mallocz(sizeof(AVDeviceInfoList));
|
||||||
|
if (!device_list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ret = ff_decklink_list_devices(avctx, device_list, show_inputs, show_outputs);
|
||||||
|
if (ret == 0) {
|
||||||
|
av_log(avctx, AV_LOG_INFO, "Blackmagic DeckLink %s devices:\n",
|
||||||
|
show_inputs ? "input" : "output");
|
||||||
|
for (int i = 0; i < device_list->nb_devices; i++) {
|
||||||
|
av_log(avctx, AV_LOG_INFO, "\t'%s'\n", device_list->devices[i]->device_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avdevice_free_list_devices(&device_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction)
|
int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction)
|
||||||
|
@ -135,7 +135,8 @@ static const BMDVideoConnection decklink_video_connection_map[] = {
|
|||||||
HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName);
|
HRESULT ff_decklink_get_display_name(IDeckLink *This, const char **displayName);
|
||||||
int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction = DIRECTION_OUT, int num = 0);
|
int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction = DIRECTION_OUT, int num = 0);
|
||||||
int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num);
|
int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num);
|
||||||
int ff_decklink_list_devices(AVFormatContext *avctx);
|
int ff_decklink_list_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list, int show_inputs, int show_outputs);
|
||||||
|
void ff_decklink_list_devices_legacy(AVFormatContext *avctx, int show_inputs, int show_outputs);
|
||||||
int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction = DIRECTION_OUT);
|
int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction = DIRECTION_OUT);
|
||||||
void ff_decklink_cleanup(AVFormatContext *avctx);
|
void ff_decklink_cleanup(AVFormatContext *avctx);
|
||||||
int ff_decklink_init_device(AVFormatContext *avctx, const char* name);
|
int ff_decklink_init_device(AVFormatContext *avctx, const char* name);
|
||||||
|
@ -39,6 +39,7 @@ extern "C" {
|
|||||||
#include "libavutil/time.h"
|
#include "libavutil/time.h"
|
||||||
#include "libavutil/mathematics.h"
|
#include "libavutil/mathematics.h"
|
||||||
#include "libavutil/reverse.h"
|
#include "libavutil/reverse.h"
|
||||||
|
#include "avdevice.h"
|
||||||
#if CONFIG_LIBZVBI
|
#if CONFIG_LIBZVBI
|
||||||
#include <libzvbi.h>
|
#include <libzvbi.h>
|
||||||
#endif
|
#endif
|
||||||
@ -868,7 +869,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
|
|||||||
|
|
||||||
/* List available devices. */
|
/* List available devices. */
|
||||||
if (ctx->list_devices) {
|
if (ctx->list_devices) {
|
||||||
ff_decklink_list_devices(avctx);
|
ff_decklink_list_devices_legacy(avctx, 1, 0);
|
||||||
return AVERROR_EXIT;
|
return AVERROR_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1063,4 +1064,9 @@ int ff_decklink_read_packet(AVFormatContext *avctx, AVPacket *pkt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ff_decklink_list_input_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list)
|
||||||
|
{
|
||||||
|
return ff_decklink_list_devices(avctx, device_list, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
@ -29,6 +29,7 @@ extern "C" {
|
|||||||
int ff_decklink_read_header(AVFormatContext *avctx);
|
int ff_decklink_read_header(AVFormatContext *avctx);
|
||||||
int ff_decklink_read_packet(AVFormatContext *avctx, AVPacket *pkt);
|
int ff_decklink_read_packet(AVFormatContext *avctx, AVPacket *pkt);
|
||||||
int ff_decklink_read_close(AVFormatContext *avctx);
|
int ff_decklink_read_close(AVFormatContext *avctx);
|
||||||
|
int ff_decklink_list_input_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
@ -89,6 +89,7 @@ AVInputFormat ff_decklink_demuxer = {
|
|||||||
.flags = AVFMT_NOFILE,
|
.flags = AVFMT_NOFILE,
|
||||||
.priv_class = &decklink_demuxer_class,
|
.priv_class = &decklink_demuxer_class,
|
||||||
.priv_data_size = sizeof(struct decklink_cctx),
|
.priv_data_size = sizeof(struct decklink_cctx),
|
||||||
|
.get_device_list = ff_decklink_list_input_devices,
|
||||||
.read_header = ff_decklink_read_header,
|
.read_header = ff_decklink_read_header,
|
||||||
.read_packet = ff_decklink_read_packet,
|
.read_packet = ff_decklink_read_packet,
|
||||||
.read_close = ff_decklink_read_close,
|
.read_close = ff_decklink_read_close,
|
||||||
|
@ -33,6 +33,7 @@ extern "C" {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#include "libavformat/avformat.h"
|
#include "libavformat/avformat.h"
|
||||||
#include "libavutil/imgutils.h"
|
#include "libavutil/imgutils.h"
|
||||||
|
#include "avdevice.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "decklink_common.h"
|
#include "decklink_common.h"
|
||||||
@ -335,9 +336,9 @@ av_cold int ff_decklink_write_header(AVFormatContext *avctx)
|
|||||||
ctx->preroll = cctx->preroll;
|
ctx->preroll = cctx->preroll;
|
||||||
cctx->ctx = ctx;
|
cctx->ctx = ctx;
|
||||||
|
|
||||||
/* List available devices. */
|
/* List available devices and exit. */
|
||||||
if (ctx->list_devices) {
|
if (ctx->list_devices) {
|
||||||
ff_decklink_list_devices(avctx);
|
ff_decklink_list_devices_legacy(avctx, 0, 1);
|
||||||
return AVERROR_EXIT;
|
return AVERROR_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,4 +401,9 @@ int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt)
|
|||||||
return AVERROR(EIO);
|
return AVERROR(EIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ff_decklink_list_output_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list)
|
||||||
|
{
|
||||||
|
return ff_decklink_list_devices(avctx, device_list, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
@ -29,6 +29,7 @@ extern "C" {
|
|||||||
int ff_decklink_write_header(AVFormatContext *avctx);
|
int ff_decklink_write_header(AVFormatContext *avctx);
|
||||||
int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt);
|
int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt);
|
||||||
int ff_decklink_write_trailer(AVFormatContext *avctx);
|
int ff_decklink_write_trailer(AVFormatContext *avctx);
|
||||||
|
int ff_decklink_list_output_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
@ -49,6 +49,7 @@ AVOutputFormat ff_decklink_muxer = {
|
|||||||
.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME,
|
.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME,
|
||||||
.subtitle_codec = AV_CODEC_ID_NONE,
|
.subtitle_codec = AV_CODEC_ID_NONE,
|
||||||
.flags = AVFMT_NOFILE,
|
.flags = AVFMT_NOFILE,
|
||||||
|
.get_device_list = ff_decklink_list_output_devices,
|
||||||
.priv_class = &decklink_muxer_class,
|
.priv_class = &decklink_muxer_class,
|
||||||
.priv_data_size = sizeof(struct decklink_cctx),
|
.priv_data_size = sizeof(struct decklink_cctx),
|
||||||
.write_header = ff_decklink_write_header,
|
.write_header = ff_decklink_write_header,
|
||||||
|
Loading…
Reference in New Issue
Block a user