blob: 01c46924d10a08a21d74cfbc607cf459a0fba855
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 "internal.h" |
25 | #include "config.h" |
26 | |
27 | #include "libavutil/ffversion.h" |
28 | const char av_device_ffversion[] = "FFmpeg version " FFMPEG_VERSION; |
29 | |
30 | #define E AV_OPT_FLAG_ENCODING_PARAM |
31 | #define D AV_OPT_FLAG_DECODING_PARAM |
32 | #define A AV_OPT_FLAG_AUDIO_PARAM |
33 | #define V AV_OPT_FLAG_VIDEO_PARAM |
34 | #define OFFSET(x) offsetof(AVDeviceCapabilitiesQuery, x) |
35 | |
36 | const AVOption av_device_capabilities[] = { |
37 | { "codec", "codec", OFFSET(codec), AV_OPT_TYPE_INT, |
38 | {.i64 = AV_CODEC_ID_NONE}, AV_CODEC_ID_NONE, INT_MAX, E|D|A|V }, |
39 | { "sample_format", "sample format", OFFSET(sample_format), AV_OPT_TYPE_SAMPLE_FMT, |
40 | {.i64 = AV_SAMPLE_FMT_NONE}, AV_SAMPLE_FMT_NONE, INT_MAX, E|D|A }, |
41 | { "sample_rate", "sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, |
42 | {.i64 = -1}, -1, INT_MAX, E|D|A }, |
43 | { "channels", "channels", OFFSET(channels), AV_OPT_TYPE_INT, |
44 | {.i64 = -1}, -1, INT_MAX, E|D|A }, |
45 | { "channel_layout", "channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, |
46 | {.i64 = -1}, -1, INT_MAX, E|D|A }, |
47 | { "pixel_format", "pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT, |
48 | {.i64 = AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, INT_MAX, E|D|V }, |
49 | { "window_size", "window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, |
50 | {.str = NULL}, -1, INT_MAX, E|D|V }, |
51 | { "frame_size", "frame size", OFFSET(frame_width), AV_OPT_TYPE_IMAGE_SIZE, |
52 | {.str = NULL}, -1, INT_MAX, E|D|V }, |
53 | { "fps", "fps", OFFSET(fps), AV_OPT_TYPE_RATIONAL, |
54 | {.dbl = -1}, -1, INT_MAX, E|D|V }, |
55 | { NULL } |
56 | }; |
57 | |
58 | #undef E |
59 | #undef D |
60 | #undef A |
61 | #undef V |
62 | #undef OFFSET |
63 | |
64 | unsigned avdevice_version(void) |
65 | { |
66 | av_assert0(LIBAVDEVICE_VERSION_MICRO >= 100); |
67 | return LIBAVDEVICE_VERSION_INT; |
68 | } |
69 | |
70 | const char * avdevice_configuration(void) |
71 | { |
72 | return FFMPEG_CONFIGURATION; |
73 | } |
74 | |
75 | const char * avdevice_license(void) |
76 | { |
77 | #define LICENSE_PREFIX "libavdevice license: " |
78 | return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; |
79 | } |
80 | |
81 | static void *device_next(void *prev, int output, |
82 | AVClassCategory c1, AVClassCategory c2) |
83 | { |
84 | const AVClass *pc; |
85 | AVClassCategory category = AV_CLASS_CATEGORY_NA; |
86 | do { |
87 | if (output) { |
88 | if (!(prev = av_oformat_next(prev))) |
89 | break; |
90 | pc = ((AVOutputFormat *)prev)->priv_class; |
91 | } else { |
92 | if (!(prev = av_iformat_next(prev))) |
93 | break; |
94 | pc = ((AVInputFormat *)prev)->priv_class; |
95 | } |
96 | if (!pc) |
97 | continue; |
98 | category = pc->category; |
99 | } while (category != c1 && category != c2); |
100 | return prev; |
101 | } |
102 | |
103 | AVInputFormat *av_input_audio_device_next(AVInputFormat *d) |
104 | { |
105 | return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, |
106 | AV_CLASS_CATEGORY_DEVICE_INPUT); |
107 | } |
108 | |
109 | AVInputFormat *av_input_video_device_next(AVInputFormat *d) |
110 | { |
111 | return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, |
112 | AV_CLASS_CATEGORY_DEVICE_INPUT); |
113 | } |
114 | |
115 | AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d) |
116 | { |
117 | return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, |
118 | AV_CLASS_CATEGORY_DEVICE_OUTPUT); |
119 | } |
120 | |
121 | AVOutputFormat *av_output_video_device_next(AVOutputFormat *d) |
122 | { |
123 | return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, |
124 | AV_CLASS_CATEGORY_DEVICE_OUTPUT); |
125 | } |
126 | |
127 | int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type, |
128 | void *data, size_t data_size) |
129 | { |
130 | if (!s->oformat || !s->oformat->control_message) |
131 | return AVERROR(ENOSYS); |
132 | return s->oformat->control_message(s, type, data, data_size); |
133 | } |
134 | |
135 | int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToAppMessageType type, |
136 | void *data, size_t data_size) |
137 | { |
138 | if (!av_format_get_control_message_cb(s)) |
139 | return AVERROR(ENOSYS); |
140 | return av_format_get_control_message_cb(s)(s, type, data, data_size); |
141 | } |
142 | |
143 | int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s, |
144 | AVDictionary **device_options) |
145 | { |
146 | int ret; |
147 | av_assert0(s && caps); |
148 | av_assert0(s->iformat || s->oformat); |
149 | if ((s->oformat && !s->oformat->create_device_capabilities) || |
150 | (s->iformat && !s->iformat->create_device_capabilities)) |
151 | return AVERROR(ENOSYS); |
152 | *caps = av_mallocz(sizeof(**caps)); |
153 | if (!(*caps)) |
154 | return AVERROR(ENOMEM); |
155 | (*caps)->device_context = s; |
156 | if (((ret = av_opt_set_dict(s->priv_data, device_options)) < 0)) |
157 | goto fail; |
158 | if (s->iformat) { |
159 | if ((ret = s->iformat->create_device_capabilities(s, *caps)) < 0) |
160 | goto fail; |
161 | } else { |
162 | if ((ret = s->oformat->create_device_capabilities(s, *caps)) < 0) |
163 | goto fail; |
164 | } |
165 | av_opt_set_defaults(*caps); |
166 | return 0; |
167 | fail: |
168 | av_freep(caps); |
169 | return ret; |
170 | } |
171 | |
172 | void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s) |
173 | { |
174 | if (!s || !caps || !(*caps)) |
175 | return; |
176 | av_assert0(s->iformat || s->oformat); |
177 | if (s->iformat) { |
178 | if (s->iformat->free_device_capabilities) |
179 | s->iformat->free_device_capabilities(s, *caps); |
180 | } else { |
181 | if (s->oformat->free_device_capabilities) |
182 | s->oformat->free_device_capabilities(s, *caps); |
183 | } |
184 | av_freep(caps); |
185 | } |
186 | |
187 | int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list) |
188 | { |
189 | int ret; |
190 | av_assert0(s); |
191 | av_assert0(device_list); |
192 | av_assert0(s->oformat || s->iformat); |
193 | if ((s->oformat && !s->oformat->get_device_list) || |
194 | (s->iformat && !s->iformat->get_device_list)) { |
195 | *device_list = NULL; |
196 | return AVERROR(ENOSYS); |
197 | } |
198 | *device_list = av_mallocz(sizeof(AVDeviceInfoList)); |
199 | if (!(*device_list)) |
200 | return AVERROR(ENOMEM); |
201 | /* no default device by default */ |
202 | (*device_list)->default_device = -1; |
203 | if (s->oformat) |
204 | ret = s->oformat->get_device_list(s, *device_list); |
205 | else |
206 | ret = s->iformat->get_device_list(s, *device_list); |
207 | if (ret < 0) |
208 | avdevice_free_list_devices(device_list); |
209 | return ret; |
210 | } |
211 | |
212 | static int list_devices_for_context(AVFormatContext *s, AVDictionary *options, |
213 | AVDeviceInfoList **device_list) |
214 | { |
215 | AVDictionary *tmp = NULL; |
216 | int ret; |
217 | |
218 | av_dict_copy(&tmp, options, 0); |
219 | if ((ret = av_opt_set_dict2(s, &tmp, AV_OPT_SEARCH_CHILDREN)) < 0) |
220 | goto fail; |
221 | ret = avdevice_list_devices(s, device_list); |
222 | fail: |
223 | av_dict_free(&tmp); |
224 | avformat_free_context(s); |
225 | return ret; |
226 | } |
227 | |
228 | int avdevice_list_input_sources(AVInputFormat *device, const char *device_name, |
229 | AVDictionary *device_options, AVDeviceInfoList **device_list) |
230 | { |
231 | AVFormatContext *s = NULL; |
232 | int ret; |
233 | |
234 | if ((ret = ff_alloc_input_device_context(&s, device, device_name)) < 0) |
235 | return ret; |
236 | return list_devices_for_context(s, device_options, device_list); |
237 | } |
238 | |
239 | int avdevice_list_output_sinks(AVOutputFormat *device, const char *device_name, |
240 | AVDictionary *device_options, AVDeviceInfoList **device_list) |
241 | { |
242 | AVFormatContext *s = NULL; |
243 | int ret; |
244 | |
245 | if ((ret = avformat_alloc_output_context2(&s, device, device_name, NULL)) < 0) |
246 | return ret; |
247 | return list_devices_for_context(s, device_options, device_list); |
248 | } |
249 | |
250 | void avdevice_free_list_devices(AVDeviceInfoList **device_list) |
251 | { |
252 | AVDeviceInfoList *list; |
253 | AVDeviceInfo *dev; |
254 | int i; |
255 | |
256 | av_assert0(device_list); |
257 | list = *device_list; |
258 | if (!list) |
259 | return; |
260 | |
261 | for (i = 0; i < list->nb_devices; i++) { |
262 | dev = list->devices[i]; |
263 | if (dev) { |
264 | av_freep(&dev->device_name); |
265 | av_freep(&dev->device_description); |
266 | av_free(dev); |
267 | } |
268 | } |
269 | av_freep(&list->devices); |
270 | av_freep(device_list); |
271 | } |
272 |