[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