Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * This file is part of FFmpeg. | |
3 | * | |
4 | * FFmpeg is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU Lesser General Public | |
6 | * License as published by the Free Software Foundation; either | |
7 | * version 2.1 of the License, or (at your option) any later version. | |
8 | * | |
9 | * FFmpeg is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * Lesser General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU Lesser General Public | |
15 | * License along with FFmpeg; if not, write to the Free Software | |
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
17 | */ | |
18 | ||
19 | #include "libavutil/avassert.h" | |
20 | #include "libavutil/samplefmt.h" | |
21 | #include "libavutil/pixfmt.h" | |
22 | #include "libavcodec/avcodec.h" | |
23 | #include "avdevice.h" | |
24 | #include "config.h" | |
25 | ||
26 | #define E AV_OPT_FLAG_ENCODING_PARAM | |
27 | #define D AV_OPT_FLAG_DECODING_PARAM | |
28 | #define A AV_OPT_FLAG_AUDIO_PARAM | |
29 | #define V AV_OPT_FLAG_VIDEO_PARAM | |
30 | #define OFFSET(x) offsetof(AVDeviceCapabilitiesQuery, x) | |
31 | ||
32 | const AVOption av_device_capabilities[] = { | |
33 | { "codec", "codec", OFFSET(codec), AV_OPT_TYPE_INT, | |
34 | {.i64 = AV_CODEC_ID_NONE}, AV_CODEC_ID_NONE, INT_MAX, E|D|A|V }, | |
35 | { "sample_format", "sample format", OFFSET(sample_format), AV_OPT_TYPE_INT, | |
36 | {.i64 = AV_SAMPLE_FMT_NONE}, -1, INT_MAX, E|D|A }, | |
37 | { "sample_rate", "sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, | |
38 | {.i64 = -1}, -1, INT_MAX, E|D|A }, | |
39 | { "channels", "channels", OFFSET(channels), AV_OPT_TYPE_INT, | |
40 | {.i64 = -1}, -1, INT_MAX, E|D|A }, | |
41 | { "channel_layout", "channel layout", OFFSET(channel_layout), AV_OPT_TYPE_INT64, | |
42 | {.i64 = -1}, -1, INT_MAX, E|D|A }, | |
43 | { "pixel_format", "pixel format", OFFSET(pixel_format), AV_OPT_TYPE_INT, | |
44 | {.i64 = AV_PIX_FMT_NONE}, -1, INT_MAX, E|D|V }, | |
45 | { "window_size", "window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, | |
46 | {.str = NULL}, -1, INT_MAX, E|D|V }, | |
47 | { "frame_size", "frame size", OFFSET(frame_width), AV_OPT_TYPE_IMAGE_SIZE, | |
48 | {.str = NULL}, -1, INT_MAX, E|D|V }, | |
49 | { "fps", "fps", OFFSET(fps), AV_OPT_TYPE_RATIONAL, | |
50 | {.dbl = -1}, -1, INT_MAX, E|D|V }, | |
51 | { NULL } | |
52 | }; | |
53 | ||
54 | #undef E | |
55 | #undef D | |
56 | #undef A | |
57 | #undef V | |
58 | #undef OFFSET | |
59 | ||
60 | unsigned avdevice_version(void) | |
61 | { | |
62 | av_assert0(LIBAVDEVICE_VERSION_MICRO >= 100); | |
63 | return LIBAVDEVICE_VERSION_INT; | |
64 | } | |
65 | ||
66 | const char * avdevice_configuration(void) | |
67 | { | |
68 | return FFMPEG_CONFIGURATION; | |
69 | } | |
70 | ||
71 | const char * avdevice_license(void) | |
72 | { | |
73 | #define LICENSE_PREFIX "libavdevice license: " | |
74 | return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; | |
75 | } | |
76 | ||
77 | static void *av_device_next(void *prev, int output, | |
78 | AVClassCategory c1, AVClassCategory c2) | |
79 | { | |
80 | const AVClass *pc; | |
81 | AVClassCategory category = AV_CLASS_CATEGORY_NA; | |
82 | do { | |
83 | if (output) { | |
84 | if (!(prev = av_oformat_next(prev))) | |
85 | break; | |
86 | pc = ((AVOutputFormat *)prev)->priv_class; | |
87 | } else { | |
88 | if (!(prev = av_iformat_next(prev))) | |
89 | break; | |
90 | pc = ((AVInputFormat *)prev)->priv_class; | |
91 | } | |
92 | if (!pc) | |
93 | continue; | |
94 | category = pc->category; | |
95 | } while (category != c1 && category != c2); | |
96 | return prev; | |
97 | } | |
98 | ||
99 | AVInputFormat *av_input_audio_device_next(AVInputFormat *d) | |
100 | { | |
101 | return av_device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, | |
102 | AV_CLASS_CATEGORY_DEVICE_INPUT); | |
103 | } | |
104 | ||
105 | AVInputFormat *av_input_video_device_next(AVInputFormat *d) | |
106 | { | |
107 | return av_device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, | |
108 | AV_CLASS_CATEGORY_DEVICE_INPUT); | |
109 | } | |
110 | ||
111 | AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d) | |
112 | { | |
113 | return av_device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, | |
114 | AV_CLASS_CATEGORY_DEVICE_OUTPUT); | |
115 | } | |
116 | ||
117 | AVOutputFormat *av_output_video_device_next(AVOutputFormat *d) | |
118 | { | |
119 | return av_device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, | |
120 | AV_CLASS_CATEGORY_DEVICE_OUTPUT); | |
121 | } | |
122 | ||
123 | int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type, | |
124 | void *data, size_t data_size) | |
125 | { | |
126 | if (!s->oformat || !s->oformat->control_message) | |
127 | return AVERROR(ENOSYS); | |
128 | return s->oformat->control_message(s, type, data, data_size); | |
129 | } | |
130 | ||
131 | int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToAppMessageType type, | |
132 | void *data, size_t data_size) | |
133 | { | |
134 | if (!s->control_message_cb) | |
135 | return AVERROR(ENOSYS); | |
136 | return s->control_message_cb(s, type, data, data_size); | |
137 | } | |
138 | ||
139 | int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s, | |
140 | AVDictionary **device_options) | |
141 | { | |
142 | int ret; | |
143 | av_assert0(s && caps); | |
144 | av_assert0(s->iformat || s->oformat); | |
145 | if ((s->oformat && !s->oformat->create_device_capabilities) || | |
146 | (s->iformat && !s->iformat->create_device_capabilities)) | |
147 | return AVERROR(ENOSYS); | |
148 | *caps = av_mallocz(sizeof(**caps)); | |
149 | if (!(*caps)) | |
150 | return AVERROR(ENOMEM); | |
151 | (*caps)->device_context = s; | |
152 | if (((ret = av_opt_set_dict(s->priv_data, device_options)) < 0)) | |
153 | goto fail; | |
154 | if (s->iformat) { | |
155 | if ((ret = s->iformat->create_device_capabilities(s, *caps)) < 0) | |
156 | goto fail; | |
157 | } else { | |
158 | if ((ret = s->oformat->create_device_capabilities(s, *caps)) < 0) | |
159 | goto fail; | |
160 | } | |
161 | av_opt_set_defaults(*caps); | |
162 | return 0; | |
163 | fail: | |
164 | av_freep(caps); | |
165 | return ret; | |
166 | } | |
167 | ||
168 | void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s) | |
169 | { | |
170 | if (!s || !caps || !(*caps)) | |
171 | return; | |
172 | av_assert0(s->iformat || s->oformat); | |
173 | if (s->iformat) { | |
174 | if (s->iformat->free_device_capabilities) | |
175 | s->iformat->free_device_capabilities(s, *caps); | |
176 | } else { | |
177 | if (s->oformat->free_device_capabilities) | |
178 | s->oformat->free_device_capabilities(s, *caps); | |
179 | } | |
180 | av_freep(caps); | |
181 | } | |
182 | ||
183 | int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list) | |
184 | { | |
185 | int ret; | |
186 | av_assert0(s); | |
187 | av_assert0(device_list); | |
188 | av_assert0(s->oformat || s->iformat); | |
189 | if ((s->oformat && !s->oformat->get_device_list) || | |
190 | (s->iformat && !s->iformat->get_device_list)) { | |
191 | *device_list = NULL; | |
192 | return AVERROR(ENOSYS); | |
193 | } | |
194 | *device_list = av_mallocz(sizeof(AVDeviceInfoList)); | |
195 | if (!(*device_list)) | |
196 | return AVERROR(ENOMEM); | |
197 | /* no default device by default */ | |
198 | (*device_list)->default_device = -1; | |
199 | if (s->oformat) | |
200 | ret = s->oformat->get_device_list(s, *device_list); | |
201 | else | |
202 | ret = s->iformat->get_device_list(s, *device_list); | |
203 | if (ret < 0) | |
204 | avdevice_free_list_devices(device_list); | |
205 | return ret; | |
206 | } | |
207 | ||
208 | void avdevice_free_list_devices(AVDeviceInfoList **device_list) | |
209 | { | |
210 | AVDeviceInfoList *list; | |
211 | AVDeviceInfo *dev; | |
212 | int i; | |
213 | ||
214 | av_assert0(device_list); | |
215 | list = *device_list; | |
216 | if (!list) | |
217 | return; | |
218 | ||
219 | for (i = 0; i < list->nb_devices; i++) { | |
220 | dev = list->devices[i]; | |
221 | if (dev) { | |
f6fa7814 DM |
222 | av_freep(&dev->device_name); |
223 | av_freep(&dev->device_description); | |
2ba45a60 DM |
224 | av_free(dev); |
225 | } | |
226 | } | |
f6fa7814 | 227 | av_freep(&list->devices); |
2ba45a60 DM |
228 | av_freep(device_list); |
229 | } |