]> git.sesse.net Git - vlc/blobdiff - modules/video_output/vmem.c
Add LGPL license
[vlc] / modules / video_output / vmem.c
index a63be9b8e24c6a612d5694bca568304231c06a41..ede49a4fde5e80d0b01e2838abe0440d67f34a0c 100644 (file)
@@ -2,7 +2,7 @@
  * vmem.c: memory video driver for vlc
  *****************************************************************************
  * Copyright (C) 2008 the VideoLAN team
- * $Id$
+ * Copyrgiht (C) 2010 RĂ©mi Denis-Courmont
  *
  * Authors: Sam Hocevar <sam@zoy.org>
  *
 #define LT_CHROMA N_("Output chroma for the memory image as a 4-character " \
                       "string, eg. \"RV32\".")
 
-#define T_LOCK N_("Lock function")
-#define LT_LOCK N_("Address of the locking callback function. This " \
-                    "function must fill in valid plane memory address " \
-                    "information for use by the video renderer.")
-
-#define T_UNLOCK N_("Unlock function")
-#define LT_UNLOCK N_("Address of the unlocking callback function")
-
-#define T_DATA N_("Callback data")
-#define LT_DATA N_("Data for the locking and unlocking functions")
-
 static int  Open (vlc_object_t *);
 static void Close(vlc_object_t *);
 
@@ -74,13 +63,17 @@ vlc_module_begin()
     set_subcategory(SUBCAT_VIDEO_VOUT)
     set_capability("vout display", 0)
 
-    add_integer("vmem-width", 320, NULL, T_WIDTH, LT_WIDTH, false)
-    add_integer("vmem-height", 200, NULL, T_HEIGHT, LT_HEIGHT, false)
-    add_integer("vmem-pitch", 640, NULL, T_PITCH, LT_PITCH, false)
-    add_string("vmem-chroma", "RV16", NULL, T_CHROMA, LT_CHROMA, true)
-    add_string("vmem-lock", "0", NULL, T_LOCK, LT_LOCK, true)
-    add_string("vmem-unlock", "0", NULL, T_UNLOCK, LT_UNLOCK, true)
-    add_string("vmem-data", "0", NULL, T_DATA, LT_DATA, true)
+    add_integer("vmem-width", 320, T_WIDTH, LT_WIDTH, false)
+        change_private()
+    add_integer("vmem-height", 200, T_HEIGHT, LT_HEIGHT, false)
+        change_private()
+    add_integer("vmem-pitch", 640, T_PITCH, LT_PITCH, false)
+        change_private()
+    add_string("vmem-chroma", "RV16", T_CHROMA, LT_CHROMA, true)
+        change_private()
+    add_obsolete_string("vmem-lock") /* obsoleted since 1.1.1 */
+    add_obsolete_string("vmem-unlock") /* obsoleted since 1.1.1 */
+    add_obsolete_string("vmem-data") /* obsoleted since 1.1.1 */
 
     set_callbacks(Open, Close)
 vlc_module_end()
@@ -89,19 +82,31 @@ vlc_module_end()
  * Local prototypes
  *****************************************************************************/
 struct picture_sys_t {
-    void (*lock)(void *sys, void **plane);
-    void (*unlock)(void *sys);
-    void *sys;
+    vout_display_sys_t *sys;
+    void *id;
 };
 
+/* NOTE: the callback prototypes must match those of LibVLC */
 struct vout_display_sys_t {
     picture_pool_t *pool;
+    unsigned        count;
+
+    void *opaque;
+    void *(*lock)(void *sys, void **plane);
+    void (*unlock)(void *sys, void *id, void *const *plane);
+    void (*display)(void *sys, void *id);
+    void (*cleanup)(void *sys);
+
+    unsigned pitches[PICTURE_PLANE_MAX];
+    unsigned lines[PICTURE_PLANE_MAX];
 };
 
+typedef unsigned (*vlc_format_cb)(void **, char *, unsigned *, unsigned *,
+                                  unsigned *, unsigned *);
+
 static picture_pool_t *Pool  (vout_display_t *, unsigned);
-static void           Display(vout_display_t *, picture_t *);
+static void           Display(vout_display_t *, picture_t *, subpicture_t *);
 static int            Control(vout_display_t *, int, va_list);
-static void           Manage (vout_display_t *);
 
 static int            Lock(picture_t *);
 static void           Unlock(picture_t *);
@@ -114,47 +119,71 @@ static void           Unlock(picture_t *);
 static int Open(vlc_object_t *object)
 {
     vout_display_t *vd = (vout_display_t *)object;
+    vout_display_sys_t *sys = malloc(sizeof(*sys));
+    if (unlikely(!sys))
+        return VLC_ENOMEM;
 
-    /* */
-    char *chroma_format = var_CreateGetString(vd, "vmem-chroma");
-    const vlc_fourcc_t chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, chroma_format);
-    free(chroma_format);
-    if (!chroma) {
-        msg_Err(vd, "vmem-chroma should be 4 characters long");
+    /* Get the callbacks */
+    vlc_format_cb setup = var_InheritAddress(vd, "vmem-setup");
+
+    sys->lock = var_InheritAddress(vd, "vmem-lock");
+    if (sys->lock == NULL) {
+        msg_Err(vd, "missing lock callback");
+        free(sys);
         return VLC_EGENERIC;
     }
+    sys->unlock = var_InheritAddress(vd, "vmem-unlock");
+    sys->display = var_InheritAddress(vd, "vmem-display");
+    sys->cleanup = var_InheritAddress(vd, "vmem-cleanup");
+    sys->opaque = var_InheritAddress(vd, "vmem-data");
+    sys->pool = NULL;
 
-    /* */
-    picture_sys_t cfg;
+    /* Define the video format */
+    video_format_t fmt = vd->fmt;
 
-    char *tmp;
-    tmp = var_CreateGetString(vd, "vmem-lock");
-    cfg.lock = (void (*)(void *, void **))(intptr_t)atoll(tmp);
-    free(tmp);
+    if (setup != NULL) {
+        char chroma[5];
 
-    tmp = var_CreateGetString(vd, "vmem-unlock");
-    cfg.unlock = (void (*)(void *))(intptr_t)atoll(tmp);
-    free(tmp);
+        memcpy(chroma, &fmt.i_chroma, 4);
+        chroma[4] = '\0';
+        memset(sys->pitches, 0, sizeof(sys->pitches));
+        memset(sys->lines, 0, sizeof(sys->lines));
 
-    tmp = var_CreateGetString(vd, "vmem-data");
-    cfg.sys = (void *)(intptr_t)atoll(tmp);
-    free(tmp);
+        sys->count = setup(&sys->opaque, chroma, &fmt.i_width, &fmt.i_height,
+                           sys->pitches, sys->lines);
+        if (sys->count == 0) {
+            msg_Err(vd, "video format setup failure (no pictures)");
+            free(sys);
+            return VLC_EGENERIC;
+        }
+        fmt.i_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, chroma);
+
+    } else {
+        char *chroma = var_InheritString(vd, "vmem-chroma");
+        fmt.i_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, chroma);
+        free(chroma);
+
+        fmt.i_width  = var_InheritInteger(vd, "vmem-width");
+        fmt.i_height = var_InheritInteger(vd, "vmem-height");
+        sys->pitches[0] = var_InheritInteger(vd, "vmem-pitch");
+        sys->lines[0] = fmt.i_height;
+        for (size_t i = 1; i < PICTURE_PLANE_MAX; i++)
+        {
+            sys->pitches[i] = sys->pitches[0];
+            sys->lines[i] = sys->lines[0];
+        }
+        sys->count = 1;
+        sys->cleanup = NULL;
+    }
 
-    /* lock and unlock are mandatory */
-    if (!cfg.lock || !cfg.unlock) {
-        msg_Err(vd, "Invalid lock or unlock callbacks");
+    if (!fmt.i_chroma) {
+        msg_Err(vd, "vmem-chroma should be 4 characters long");
+        free(sys);
         return VLC_EGENERIC;
     }
 
-    /* */
-    video_format_t fmt = vd->fmt;
-
-    fmt.i_chroma = chroma;
-    fmt.i_width  = var_CreateGetInteger(vd, "vmem-width");
-    fmt.i_height = var_CreateGetInteger(vd, "vmem-height");
-
     /* Define the bitmasks */
-    switch (chroma)
+    switch (fmt.i_chroma)
     {
     case VLC_CODEC_RGB15:
         fmt.i_rmask = 0x001f;
@@ -167,10 +196,6 @@ static int Open(vlc_object_t *object)
         fmt.i_bmask = 0xf800;
         break;
     case VLC_CODEC_RGB24:
-        fmt.i_rmask = 0xff0000;
-        fmt.i_gmask = 0x00ff00;
-        fmt.i_bmask = 0x0000ff;
-        break;
     case VLC_CODEC_RGB32:
         fmt.i_rmask = 0xff0000;
         fmt.i_gmask = 0x00ff00;
@@ -183,56 +208,19 @@ static int Open(vlc_object_t *object)
         break;
     }
 
-    /* */
-    vout_display_sys_t *sys;
-    vd->sys = sys = calloc(1, sizeof(*sys));
-    if (!sys)
-        return VLC_EGENERIC;
-
-    /* */
-    const int pitch = var_CreateGetInteger(vd, "vmem-pitch");
-    picture_resource_t rsc;
-    rsc.p_sys = malloc(sizeof(*rsc.p_sys));
-    *rsc.p_sys = cfg;
-    for (int i = 0; i < PICTURE_PLANE_MAX; i++) {
-        /* vmem-lock is responsible for the allocation */
-        rsc.p[i].p_pixels = NULL;
-        rsc.p[i].i_lines  = fmt.i_height;
-        rsc.p[i].i_pitch  = pitch;
-    }
-    picture_t *picture = picture_NewFromResource(&fmt, &rsc);
-    if (!picture) {
-        free(rsc.p_sys);
-        free(sys);
-        return VLC_EGENERIC;
-    }
-
-    /* */
-    picture_pool_configuration_t pool;
-    memset(&pool, 0, sizeof(pool));
-    pool.picture_count = 1;
-    pool.picture       = &picture;
-    pool.lock          = Lock;
-    pool.unlock        = Unlock;
-    sys->pool = picture_pool_NewExtended(&pool);
-    if (!sys->pool) {
-        picture_Release(picture);
-        free(sys);
-        return VLC_SUCCESS;
-    }
-
     /* */
     vout_display_info_t info = vd->info;
     info.has_hide_mouse = true;
 
     /* */
+    vd->sys     = sys;
     vd->fmt     = fmt;
     vd->info    = info;
     vd->pool    = Pool;
     vd->prepare = NULL;
     vd->display = Display;
     vd->control = Control;
-    vd->manage  = Manage;
+    vd->manage  = NULL;
 
     /* */
     vout_display_SendEventFullscreen(vd, false);
@@ -245,6 +233,8 @@ static void Close(vlc_object_t *object)
     vout_display_t *vd = (vout_display_t *)object;
     vout_display_sys_t *sys = vd->sys;
 
+    if (sys->cleanup)
+        sys->cleanup(sys->opaque);
     picture_pool_Delete(sys->pool);
     free(sys);
 }
@@ -252,16 +242,70 @@ static void Close(vlc_object_t *object)
 /* */
 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
 {
-    VLC_UNUSED(count);
-    return vd->sys->pool;
+    vout_display_sys_t *sys = vd->sys;
+
+    if (sys->pool)
+        return sys->pool;
+
+    if (count > sys->count)
+        count = sys->count;
+
+    picture_t *pictures[count];
+
+    for (unsigned i = 0; i < count; i++) {
+        picture_resource_t rsc;
+
+        rsc.p_sys = malloc(sizeof(*rsc.p_sys));
+        if (unlikely(!rsc.p_sys)) {
+            count = i;
+            break;
+        }
+
+        rsc.p_sys->sys = sys;
+        rsc.p_sys->id = NULL;
+
+        for (unsigned i = 0; i < PICTURE_PLANE_MAX; i++) {
+            /* vmem-lock is responsible for the allocation */
+            rsc.p[i].p_pixels = NULL;
+            rsc.p[i].i_lines  = sys->lines[i];
+            rsc.p[i].i_pitch  = sys->pitches[i];
+        }
+
+        pictures[i] = picture_NewFromResource(&vd->fmt, &rsc);
+        if (!pictures[i]) {
+            free(rsc.p_sys);
+            count = i;
+            break;
+        }
+    }
+
+    /* */
+    picture_pool_configuration_t pool;
+    memset(&pool, 0, sizeof(pool));
+    pool.picture_count = count;
+    pool.picture       = pictures;
+    pool.lock          = Lock;
+    pool.unlock        = Unlock;
+    sys->pool = picture_pool_NewExtended(&pool);
+    if (!sys->pool) {
+        for (unsigned i = 0; i < count; i++)
+            picture_Release(pictures[i]);
+    }
+
+    return sys->pool;
 }
 
-static void Display(vout_display_t *vd, picture_t *picture)
+static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
 {
-    VLC_UNUSED(vd);
+    vout_display_sys_t *sys = vd->sys;
+
     assert(!picture_IsReferenced(picture));
+    if (sys->display != NULL)
+        sys->display(sys->opaque, picture->p_sys->id);
     picture_Release(picture);
+    VLC_UNUSED(subpicture);
 }
+
 static int Control(vout_display_t *vd, int query, va_list args)
 {
     switch (query) {
@@ -279,28 +323,32 @@ static int Control(vout_display_t *vd, int query, va_list args)
         return VLC_EGENERIC;
     }
 }
-static void Manage(vout_display_t *vd)
-{
-    VLC_UNUSED(vd);
-}
 
 /* */
 static int Lock(picture_t *picture)
 {
-    picture_sys_t *sys = picture->p_sys;
-
+    picture_sys_t *picsys = picture->p_sys;
+    vout_display_sys_t *sys = picsys->sys;
     void *planes[PICTURE_PLANE_MAX];
-    sys->lock(sys->sys, planes);
+
+    picsys->id = sys->lock(sys->opaque, planes);
 
     for (int i = 0; i < picture->i_planes; i++)
         picture->p[i].p_pixels = planes[i];
 
     return VLC_SUCCESS;
 }
+
 static void Unlock(picture_t *picture)
 {
-    picture_sys_t *sys = picture->p_sys;
+    picture_sys_t *picsys = picture->p_sys;
+    vout_display_sys_t *sys = picsys->sys;
 
-    sys->unlock(sys->sys);
-}
+    void *planes[PICTURE_PLANE_MAX];
+
+    for (int i = 0; i < picture->i_planes; i++)
+        planes[i] = picture->p[i].p_pixels;
 
+    if (sys->unlock != NULL)
+        sys->unlock(sys->opaque, picsys->id, planes);
+}