[FFmpeg-devel] [PATCH 4/4] examples: opengl_device_settings
Lukasz Marek
lukasz.m.luki at gmail.com
Fri Feb 7 14:35:03 CET 2014
Just a testing tool. Do not merge.
---
doc/examples/Makefile | 1 +
doc/examples/opengl_device_settings.c | 204 ++++++++++++++++++++++++++++++++++
2 files changed, 205 insertions(+)
create mode 100644 doc/examples/opengl_device_settings.c
diff --git a/doc/examples/Makefile b/doc/examples/Makefile
index f4f6c70..73b07da 100644
--- a/doc/examples/Makefile
+++ b/doc/examples/Makefile
@@ -22,6 +22,7 @@ EXAMPLES= avio_reading \
resampling_audio \
scaling_video \
transcode_aac \
+ opengl_device_settings \
OBJS=$(addsuffix .o,$(EXAMPLES))
diff --git a/doc/examples/opengl_device_settings.c b/doc/examples/opengl_device_settings.c
new file mode 100644
index 0000000..2d04fd6
--- /dev/null
+++ b/doc/examples/opengl_device_settings.c
@@ -0,0 +1,204 @@
+
+#include <SDL/SDL.h>
+#include <libavutil/log.h>
+#include <libavutil/pixdesc.h>
+#include <libavutil/opt.h>
+#include <libavformat/avformat.h>
+#include <libavdevice/avdevice.h>
+
+SDL_Surface *g_surface = NULL;
+
+static int av_cold create_sdl_window(int width, int height)
+{
+ if (SDL_Init(SDL_INIT_VIDEO)) {
+ av_log(NULL, AV_LOG_ERROR, "Unable to initialize SDL: %s\n", SDL_GetError());
+ return AVERROR_EXTERNAL;
+ }
+ g_surface = SDL_SetVideoMode(width, height, 32, SDL_OPENGL);
+ if (!g_surface) {
+ av_log(NULL, AV_LOG_ERROR, "Unable to set video mode: %s\n", SDL_GetError());
+ return AVERROR_EXTERNAL;
+ }
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_WM_SetCaption("OpenGL example", NULL);
+ return 0;
+}
+
+static int message_from_device_handler(struct AVFormatContext *s, int type,
+ void *data, size_t data_size)
+{
+ switch ((enum AVDevToAppMessageType) type) {
+ case AV_DEV_TO_APP_CREATE_WINDOW_BUFFER:
+ if (!g_surface)
+ return create_sdl_window(1, 1);
+ return 0;
+ case AV_DEV_TO_APP_DESTROY_WINDOW_BUFFER:
+ SDL_Quit();
+ g_surface = NULL;
+ return 0;
+ case AV_DEV_TO_APP_PREPARE_WINDOW_BUFFER:
+ //SDL 1.2 doesn't required it (no such API),
+ //but you need to make OpenGL context current here.
+ return 0;
+ case AV_DEV_TO_APP_DISPLAY_WINDOW_BUFFER:
+ SDL_GL_SwapBuffers();
+ return 0;
+ default:
+ break;
+ }
+ return AVERROR(ENOSYS);
+}
+
+static int print_ranges(AVDeviceCapabilitiesQuery *query, const char *cap_name)
+{
+ int i;
+ AVOptionRanges *ranges;
+ AVOptionRange *range;
+
+ if ((i = av_opt_query_ranges(&ranges, query, cap_name, 0)) < 0) {
+ av_log(query, AV_LOG_ERROR, "Cannot query range of %s\n", cap_name);
+ return i;
+ }
+ av_log(query, AV_LOG_INFO, "%-14s: allowed values: ", cap_name);
+ for (i = 0; i < ranges->nb_ranges; i++) {
+ range = ranges->range[i];
+ if (i)
+ av_log(query, AV_LOG_INFO, ", ");
+ if (range->is_range)
+ if (!strcmp(cap_name, "devcap_fps"))
+ av_log(query, AV_LOG_INFO, "%.5f - %.5f", range->value_min, range->value_max);
+ else
+ av_log(query, AV_LOG_INFO, "%d - %d", (int)range->value_min, (int)range->value_max);
+ else {
+ if (!strcmp(cap_name, "devcap_fps"))
+ av_log(query, AV_LOG_INFO, "%.5f", range->value_min);
+ else if (!strcmp(cap_name, "devcap_format"))
+ av_log(query, AV_LOG_INFO, "%s", av_get_pix_fmt_name((int)range->value_min));
+ else if (!strcmp(cap_name, "devcap_codec"))
+ av_log(query, AV_LOG_INFO, "%s", avcodec_get_name((int)range->value_min));
+ else
+ av_log(query, AV_LOG_INFO, "%d", (int)range->value_min);
+ }
+ }
+ av_log(query, AV_LOG_INFO, "\n");
+ av_opt_freep_ranges(&ranges);
+ return 0;
+}
+
+void print_all(AVDeviceCapabilitiesQuery *query)
+{
+ print_ranges(query, "devcap_window_width");
+ print_ranges(query, "devcap_window_height");
+ print_ranges(query, "devcap_frame_width");
+ print_ranges(query, "devcap_frame_height");
+ print_ranges(query, "devcap_fps");
+ print_ranges(query, "devcap_codec");
+ print_ranges(query, "devcap_format");
+}
+
+int set_video_configuration(AVFormatContext *oc)
+{
+ int ret;
+ AVDictionary *opts = NULL;
+ AVDeviceCapabilitiesQuery *query;
+ AVDeviceInfoList *devices;
+
+ av_dict_set(&opts, "no_window", "1", 0);
+ ret = avdevice_capabilities_create(&query, oc, &opts);
+ av_dict_free(&opts);
+ if (ret < 0) {
+ if (ret == AVERROR(ENOSYS))
+ av_log(oc, AV_LOG_ERROR, "Device doesn't provide this API.\n");
+ else
+ av_log(oc, AV_LOG_ERROR, "Error occurred.\n");
+ return ret;
+ }
+
+ if ((ret = avdevice_list_devices(oc, &devices)) < 0)
+ goto fail;
+ if (!devices->nb_devices) {
+ av_log(oc, AV_LOG_WARNING, "No devices found");
+ ret = -1;
+ goto fail;
+ }
+ if (devices->default_device < 0)
+ devices->default_device = 0;
+
+ av_log(oc, AV_LOG_INFO, "Using device: %s\n", devices->devices[devices->default_device].device_description);
+ av_opt_set(query, "devcap_device_name",
+ devices->devices[devices->default_device].device_name, 0);
+ avdevice_free_list_devices(&devices);
+
+ av_log(oc, AV_LOG_INFO, "Parameter ranges accepted by OpenGL device are:\n");
+ print_all(query);
+
+ av_log(oc, AV_LOG_INFO, "\n");
+ av_log(oc, AV_LOG_INFO, "Parameter ranges accepted by OpenGL device for devcap_window_width == 100000 are:\n");
+ av_opt_set_int(query, "devcap_window_width", 100000, 0);
+ print_all(query);
+
+ av_opt_set_int(query, "devcap_window_width", 256, 0);
+ av_opt_set_int(query, "devcap_window_height", 256, 0);
+ av_opt_set_int(query, "devcap_frame_width", 256, 0);
+ av_opt_set_int(query, "devcap_frame_height", 256, 0);
+ //Set codec to raw video
+ av_opt_set_int(query, "devcap_codec", AV_CODEC_ID_RAWVIDEO, 0);
+ //60 frames per second, fps is ignored by OpenGL device, but it can be set
+ av_opt_set_q(query, "devcap_fps", (AVRational){60, 1}, 0);
+ //set RGB24 format: each component is 1 byte long and no alpha
+ av_opt_set_int(query, "devcap_format", AV_PIX_FMT_RGB24, 0);
+
+ av_log(oc, AV_LOG_INFO, "\n");
+ av_log(oc, AV_LOG_INFO, "Current OpenGL device configuration:\n");
+ print_all(query);
+
+ ret = avdevice_capabilities_apply(query, oc, AVDeviceApplyStrategyApplyFixToTheNearest);
+ if (!ret) {
+ av_log(oc, AV_LOG_ERROR, "Provided configuration is wrong!\n");
+ ret = -1;
+ goto fail;
+ } else if (ret < 0) {
+ av_log(oc, AV_LOG_ERROR, "Error occurred\n");
+ goto fail;
+ } else
+ av_log(oc, AV_LOG_INFO, "Configuration accepted!\n");
+
+ avdevice_capabilities_free(&query, oc);
+
+ return 0;
+ fail:
+ avdevice_capabilities_free(&query, oc);
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+ AVFormatContext *oc;
+
+ //av_log_set_level(AV_LOG_DEBUG);
+
+ av_register_all();
+ avdevice_register_all();
+
+ /* allocate the output media context */
+ ret = avformat_alloc_output_context2(&oc, NULL, "opengl", NULL);
+ if (ret < 0 || !oc) {
+ av_log(NULL, AV_LOG_ERROR, "Could not allocate output format context.\n");
+ return 1;
+ }
+
+ av_format_set_control_message_cb(oc, message_from_device_handler);
+
+ set_video_configuration(oc);
+
+ av_log(oc, AV_LOG_INFO, "To be continued...\n");
+
+ avformat_free_context(oc);
+
+ return 0;
+}
--
1.8.3.2
More information about the ffmpeg-devel
mailing list