[FFmpeg-devel] [PATCH 4/4] examples: opengl_device_settings

Lukasz Marek lukasz.m.luki at gmail.com
Mon Feb 3 01:02:51 CET 2014


Just a testing tool. Do not merge.
---
 doc/examples/Makefile                 |   1 +
 doc/examples/opengl_device_settings.c | 176 ++++++++++++++++++++++++++++++++++
 2 files changed, 177 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..3debcc5
--- /dev/null
+++ b/doc/examples/opengl_device_settings.c
@@ -0,0 +1,176 @@
+
+#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);
+    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(AVFormatContext *oc, enum AVDeviceCapability cap,
+                        const char *cap_name)
+{
+    int i;
+    AVOptionRanges *ranges;
+    AVOptionRange *range;
+
+    if ((i = avdevice_get_device_capability(oc, cap, &ranges)) < 0) {
+        av_log(oc, AV_LOG_ERROR, "Cannot query range of %s\n", cap_name);
+        return i;
+    }
+    av_log(oc, AV_LOG_INFO, "%-14s: allowed values: ", cap_name);
+    for(i = 0; i < ranges->nb_ranges; i++) {
+        range = ranges->range[i];
+        if (i)
+            av_log(oc, AV_LOG_INFO, ", ");
+        if (range->is_range)
+            if (cap == AV_DEV_CAP_FPS)
+                av_log(oc, AV_LOG_INFO, "%.5f - %.5f", range->value_min, range->value_max);
+            else
+                av_log(oc, AV_LOG_INFO, "%d - %d", (int)range->value_min, (int)range->value_max);
+        else {
+            if (cap == AV_DEV_CAP_FPS)
+                av_log(oc, AV_LOG_INFO, "%.5f", range->value_min);
+            if (cap == AV_DEV_CAP_FORMAT)
+                av_log(oc, AV_LOG_INFO, "%s", av_get_pix_fmt_name((int)range->value_min));
+            else if (cap == AV_DEV_CAP_CODEC_ID)
+                av_log(oc, AV_LOG_INFO, "%s", avcodec_get_name((int)range->value_min));
+            else
+                av_log(oc, AV_LOG_INFO, "%d", (int)range->value_min);
+        }
+    }
+    av_log(oc, AV_LOG_INFO, "\n");
+    av_opt_freep_ranges(&ranges);
+    return 0;
+}
+
+void print_all(AVFormatContext *oc)
+{
+    print_ranges(oc, AV_DEV_CAP_WINDOW_WIDTH, "window width");
+    print_ranges(oc, AV_DEV_CAP_WINDOW_HEIGHT, "window height");
+    print_ranges(oc, AV_DEV_CAP_FRAME_WIDTH, "frame width");
+    print_ranges(oc, AV_DEV_CAP_FRAME_HEIGHT, "frame height");
+    print_ranges(oc, AV_DEV_CAP_FPS, "fps");
+    print_ranges(oc, AV_DEV_CAP_CODEC_ID, "codec");
+    print_ranges(oc, AV_DEV_CAP_FORMAT, "format");
+}
+
+int set_video_configuration(AVFormatContext *oc)
+{
+    int ret;
+    AVDictionary *opts = NULL;
+    AVDeviceCapabilities *spec;
+
+    av_dict_set(&opts, "no_window", "1", 0);
+    ret = avdevice_init_device_capabilities(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;
+    }
+
+    av_log(oc, AV_LOG_INFO, "Parameter ranges accepted by OpenGL device are:\n");
+    print_all(oc);
+
+    avdevice_set_device_capability_int(oc, AV_DEV_CAP_WINDOW_WIDTH, 256);
+    avdevice_set_device_capability_int(oc, AV_DEV_CAP_WINDOW_HEIGHT, 256);
+    avdevice_set_device_capability_int(oc, AV_DEV_CAP_FRAME_WIDTH, 256);
+    avdevice_set_device_capability_int(oc, AV_DEV_CAP_FRAME_HEIGHT, 256);
+    //Set codec to raw video
+    avdevice_set_device_capability_int(oc, AV_DEV_CAP_CODEC_ID, AV_CODEC_ID_RAWVIDEO);
+    //60 frames per second, fps is ignored by OpenGL device, but it can be set
+    avdevice_set_device_capability_q(oc, AV_DEV_CAP_FPS, (AVRational){60, 1});
+    //set RGB24 format: each component is 1 byte long and no alpha
+    avdevice_set_device_capability_int(oc, AV_DEV_CAP_FORMAT, AV_PIX_FMT_RGB24);
+
+    av_log(oc, AV_LOG_INFO, "\n");
+    av_log(oc, AV_LOG_INFO, "Current OpenGL device configuration:\n");
+    print_all(oc);
+
+    avdevice_finish_device_capabilities(oc, &spec, AVDeviceApplyStrategyAbandonNotValid);
+    if (!spec) {
+        av_log(oc, AV_LOG_ERROR, "Provided configuration is wrong!\n");
+        return -1;
+    } else
+        av_log(oc, AV_LOG_INFO, "Configuration accepted!\n");
+
+    avdevice_free_device_capabilities(&spec);
+
+    return 0;
+}
+
+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