Skip to content

Commit

Permalink
lavd: add new API for iterating input and output devices
Browse files Browse the repository at this point in the history
This also adds an avpriv function to register devices in
libavformat
  • Loading branch information
jdek committed Feb 6, 2018
1 parent 0694d87 commit 0fd4757
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 96 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ distclean:: clean
version.h libavutil/ffversion.h libavcodec/codec_names.h \
libavcodec/bsf_list.c libavformat/protocol_list.c \
libavcodec/codec_list.c libavcodec/parser_list.c \
libavformat/muxer_list.c libavformat/demuxer_list.c
libavformat/muxer_list.c libavformat/demuxer_list.c \
libavdevice/indev_list.c libavdevice/outdev_list.c
ifeq ($(SRC_LINK),src)
$(RM) src
endif
Expand Down
27 changes: 23 additions & 4 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,12 @@ add_suffix(){
for v; do echo ${v}${suffix}; done
}

remove_suffix(){
suffix=$1
shift
for v; do echo ${v%$suffix}; done
}

set_all(){
value=$1
shift
Expand Down Expand Up @@ -3525,17 +3531,18 @@ find_things(){
sed -n "s/^[^#]*$pattern.*([^,]*, *\([^,]*\)\(,.*\)*).*/\1_$thing/p" "$file"
}

OUTDEV_LIST=$(find_things outdev OUTDEV libavdevice/alldevices.c)
INDEV_LIST=$(find_things indev _IN libavdevice/alldevices.c)
FILTER_LIST=$(find_things filter FILTER libavfilter/allfilters.c)

find_things_extern(){
thing=$1
pattern=$2
file=$source_path/$3
sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file"
out=${4:-$thing}
sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$out/p" "$file"
}

OUTDEV_LIST=$(find_things_extern muxer AVOutputFormat libavdevice/alldevices.c outdev)
INDEV_LIST=$(find_things_extern demuxer AVInputFormat libavdevice/alldevices.c indev)
MUXER_LIST=$(find_things_extern muxer AVOutputFormat libavformat/allformats.c)
DEMUXER_LIST=$(find_things_extern demuxer AVInputFormat libavformat/allformats.c)
ENCODER_LIST=$(find_things_extern encoder AVCodec libavcodec/allcodecs.c)
Expand Down Expand Up @@ -7027,7 +7034,17 @@ print_enabled_components(){
shift 3
echo "static const $struct_name * const $name[] = {" > $TMPH
for c in $*; do
enabled $c && printf " &ff_%s,\n" $c >> $TMPH
if enabled $c; then
case $name in
indev_list)
c=$(add_suffix _demuxer $(remove_suffix _indev $c))
;;
outdev_list)
c=$(add_suffix _muxer $(remove_suffix _outdev $c))
;;
esac
printf " &ff_%s,\n" $c >> $TMPH
fi
done
echo " NULL };" >> $TMPH
cp_if_changed $TMPH $file
Expand All @@ -7036,6 +7053,8 @@ print_enabled_components(){
print_enabled_components libavcodec/codec_list.c AVCodec codec_list $CODEC_LIST
print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PARSER_LIST
print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST
print_enabled_components libavdevice/indev_list.c AVInputFormat indev_list $INDEV_LIST
print_enabled_components libavdevice/outdev_list.c AVOutputFormat outdev_list $OUTDEV_LIST
print_enabled_components libavformat/demuxer_list.c AVInputFormat demuxer_list $DEMUXER_LIST
print_enabled_components libavformat/muxer_list.c AVOutputFormat muxer_list $MUXER_LIST
print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST
Expand Down
2 changes: 2 additions & 0 deletions libavdevice/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/indev_list.c
/outdev_list.c
181 changes: 138 additions & 43 deletions libavdevice/alldevices.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,57 +22,152 @@
#include "libavutil/thread.h"
#include "avdevice.h"

#define REGISTER_OUTDEV(X, x) \
{ \
extern AVOutputFormat ff_##x##_muxer; \
if (CONFIG_##X##_OUTDEV) \
av_register_output_format(&ff_##x##_muxer); \
#if FF_API_NEXT
#include "libavformat/internal.h"
#endif

/* devices */
extern AVInputFormat ff_alsa_demuxer;
extern AVOutputFormat ff_alsa_muxer;
extern AVInputFormat ff_avfoundation_demuxer;
extern AVInputFormat ff_bktr_demuxer;
extern AVOutputFormat ff_caca_muxer;
extern AVInputFormat ff_decklink_demuxer;
extern AVOutputFormat ff_decklink_muxer;
extern AVInputFormat ff_libndi_newtek_demuxer;
extern AVOutputFormat ff_libndi_newtek_muxer;
extern AVInputFormat ff_dshow_demuxer;
extern AVInputFormat ff_fbdev_demuxer;
extern AVOutputFormat ff_fbdev_muxer;
extern AVInputFormat ff_gdigrab_demuxer;
extern AVInputFormat ff_iec61883_demuxer;
extern AVInputFormat ff_jack_demuxer;
extern AVInputFormat ff_kmsgrab_demuxer;
extern AVInputFormat ff_lavfi_demuxer;
extern AVInputFormat ff_openal_demuxer;
extern AVOutputFormat ff_opengl_muxer;
extern AVInputFormat ff_oss_demuxer;
extern AVOutputFormat ff_oss_muxer;
extern AVInputFormat ff_pulse_demuxer;
extern AVOutputFormat ff_pulse_muxer;
extern AVOutputFormat ff_sdl2_muxer;
extern AVInputFormat ff_sndio_demuxer;
extern AVOutputFormat ff_sndio_muxer;
extern AVInputFormat ff_v4l2_demuxer;
extern AVOutputFormat ff_v4l2_muxer;
extern AVInputFormat ff_vfwcap_demuxer;
extern AVInputFormat ff_xcbgrab_demuxer;
extern AVOutputFormat ff_xv_muxer;

/* external libraries */
extern AVInputFormat ff_libcdio_demuxer;
extern AVInputFormat ff_libdc1394_demuxer;

#include "libavdevice/outdev_list.c"
#include "libavdevice/indev_list.c"

const AVOutputFormat *av_outdev_iterate(void **opaque)
{
uintptr_t i = (uintptr_t)*opaque;
const AVOutputFormat *f = outdev_list[i];

if (f)
*opaque = (void*)(i + 1);
return f;
}

const AVInputFormat *av_indev_iterate(void **opaque)
{
uintptr_t i = (uintptr_t)*opaque;
const AVInputFormat *f = indev_list[i];

if (f)
*opaque = (void*)(i + 1);
return f;
}

#if FF_API_NEXT
FF_DISABLE_DEPRECATION_WARNINGS
static AVOnce av_device_next_init = AV_ONCE_INIT;

static void av_device_init_next(void)
{
AVOutputFormat *prevout = NULL, *out;
AVInputFormat *previn = NULL, *in;
void *i = 0;

while ((out = (AVOutputFormat*)av_outdev_iterate(&i))) {
if (prevout)
prevout->next = out;
prevout = out;
}

#define REGISTER_INDEV(X, x) \
{ \
extern AVInputFormat ff_##x##_demuxer; \
if (CONFIG_##X##_INDEV) \
av_register_input_format(&ff_##x##_demuxer); \
i = 0;
while ((in = (AVInputFormat*)av_indev_iterate(&i))) {
if (previn)
previn->next = in;
previn = in;
}

#define REGISTER_INOUTDEV(X, x) REGISTER_OUTDEV(X, x); REGISTER_INDEV(X, x)
avpriv_register_devices(outdev_list, indev_list);
}

static void register_all(void)
void avdevice_register_all(void)
{
/* devices */
REGISTER_INOUTDEV(ALSA, alsa);
REGISTER_INDEV (AVFOUNDATION, avfoundation);
REGISTER_INDEV (BKTR, bktr);
REGISTER_OUTDEV (CACA, caca);
REGISTER_INOUTDEV(DECKLINK, decklink);
REGISTER_INOUTDEV(LIBNDI_NEWTEK, libndi_newtek);
REGISTER_INDEV (DSHOW, dshow);
REGISTER_INOUTDEV(FBDEV, fbdev);
REGISTER_INDEV (GDIGRAB, gdigrab);
REGISTER_INDEV (IEC61883, iec61883);
REGISTER_INDEV (JACK, jack);
REGISTER_INDEV (KMSGRAB, kmsgrab);
REGISTER_INDEV (LAVFI, lavfi);
REGISTER_INDEV (OPENAL, openal);
REGISTER_OUTDEV (OPENGL, opengl);
REGISTER_INOUTDEV(OSS, oss);
REGISTER_INOUTDEV(PULSE, pulse);
REGISTER_OUTDEV (SDL2, sdl2);
REGISTER_INOUTDEV(SNDIO, sndio);
REGISTER_INOUTDEV(V4L2, v4l2);
REGISTER_INDEV (VFWCAP, vfwcap);
REGISTER_INDEV (XCBGRAB, xcbgrab);
REGISTER_OUTDEV (XV, xv);

/* external libraries */
REGISTER_INDEV (LIBCDIO, libcdio);
REGISTER_INDEV (LIBDC1394, libdc1394);
ff_thread_once(&av_device_next_init, av_device_init_next);
}

void avdevice_register_all(void)
static void *device_next(void *prev, int output,
AVClassCategory c1, AVClassCategory c2)
{
const AVClass *pc;
AVClassCategory category = AV_CLASS_CATEGORY_NA;

ff_thread_once(&av_device_next_init, av_device_init_next);

if (!prev && !(prev = (output ? (void*)outdev_list[0] : (void*)indev_list[0])))
return NULL;

do {
if (output) {
if (!(prev = ((AVOutputFormat *)prev)->next))
break;
pc = ((AVOutputFormat *)prev)->priv_class;
} else {
if (!(prev = ((AVInputFormat *)prev)->next))
break;
pc = ((AVInputFormat *)prev)->priv_class;
}
if (!pc)
continue;
category = pc->category;
} while (category != c1 && category != c2);
return prev;
}

AVInputFormat *av_input_audio_device_next(AVInputFormat *d)
{
return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,
AV_CLASS_CATEGORY_DEVICE_INPUT);
}

AVInputFormat *av_input_video_device_next(AVInputFormat *d)
{
return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,
AV_CLASS_CATEGORY_DEVICE_INPUT);
}

AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d)
{
static AVOnce control = AV_ONCE_INIT;
return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT,
AV_CLASS_CATEGORY_DEVICE_OUTPUT);
}

ff_thread_once(&control, register_all);
AVOutputFormat *av_output_video_device_next(AVOutputFormat *d)
{
return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT,
AV_CLASS_CATEGORY_DEVICE_OUTPUT);
}
FF_DISABLE_DEPRECATION_WARNINGS
#endif

46 changes: 0 additions & 46 deletions libavdevice/avdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,52 +78,6 @@ const char * avdevice_license(void)
return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
}

static void *device_next(void *prev, int output,
AVClassCategory c1, AVClassCategory c2)
{
const AVClass *pc;
AVClassCategory category = AV_CLASS_CATEGORY_NA;
do {
if (output) {
if (!(prev = av_oformat_next(prev)))
break;
pc = ((AVOutputFormat *)prev)->priv_class;
} else {
if (!(prev = av_iformat_next(prev)))
break;
pc = ((AVInputFormat *)prev)->priv_class;
}
if (!pc)
continue;
category = pc->category;
} while (category != c1 && category != c2);
return prev;
}

AVInputFormat *av_input_audio_device_next(AVInputFormat *d)
{
return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,
AV_CLASS_CATEGORY_DEVICE_INPUT);
}

AVInputFormat *av_input_video_device_next(AVInputFormat *d)
{
return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,
AV_CLASS_CATEGORY_DEVICE_INPUT);
}

AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d)
{
return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT,
AV_CLASS_CATEGORY_DEVICE_OUTPUT);
}

AVOutputFormat *av_output_video_device_next(AVOutputFormat *d)
{
return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT,
AV_CLASS_CATEGORY_DEVICE_OUTPUT);
}

int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type,
void *data, size_t data_size)
{
Expand Down
28 changes: 28 additions & 0 deletions libavdevice/avdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,29 @@ const char *avdevice_configuration(void);
*/
const char *avdevice_license(void);

/**
* Iterate over all registered output devices.
*
* @param opaque a pointer where libavdevice will store the iteration state. Must
* point to NULL to start the iteration.
*
* @return the next registered output device or NULL when the iteration is
* finished
*/
const AVOutputFormat *av_outdev_iterate(void **opaque);

/**
* Iterate over all registered input devices.
*
* @param opaque a pointer where libavdevice will store the iteration state. Must
* point to NULL to start the iteration.
*
* @return the next registered input device or NULL when the iteration is
* finished
*/
const AVInputFormat *av_indev_iterate(void **opaque);

#if FF_API_NEXT
/**
* Initialize libavdevice and register all the input and output devices.
*/
Expand All @@ -77,6 +100,7 @@ void avdevice_register_all(void);
* if d is non-NULL, returns the next registered input audio/video device after d
* or NULL if d is the last one.
*/
attribute_deprecated
AVInputFormat *av_input_audio_device_next(AVInputFormat *d);

/**
Expand All @@ -86,6 +110,7 @@ AVInputFormat *av_input_audio_device_next(AVInputFormat *d);
* if d is non-NULL, returns the next registered input audio/video device after d
* or NULL if d is the last one.
*/
attribute_deprecated
AVInputFormat *av_input_video_device_next(AVInputFormat *d);

/**
Expand All @@ -95,6 +120,7 @@ AVInputFormat *av_input_video_device_next(AVInputFormat *d);
* if d is non-NULL, returns the next registered output audio/video device after d
* or NULL if d is the last one.
*/
attribute_deprecated
AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d);

/**
Expand All @@ -104,7 +130,9 @@ AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d);
* if d is non-NULL, returns the next registered output audio/video device after d
* or NULL if d is the last one.
*/
attribute_deprecated
AVOutputFormat *av_output_video_device_next(AVOutputFormat *d);
#endif

typedef struct AVDeviceRect {
int x; /**< x coordinate of top left corner */
Expand Down
4 changes: 4 additions & 0 deletions libavdevice/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,8 @@
* the public API and may change, break or disappear at any time.
*/

#ifndef FF_API_NEXT
#define FF_API_NEXT (LIBAVDEVICE_VERSION_MAJOR < 59)
#endif

#endif /* AVDEVICE_VERSION_H */
Loading

0 comments on commit 0fd4757

Please sign in to comment.