]> git.sesse.net Git - vlc/blobdiff - modules/video_output/vmem.c
macosx: video effects: fix threshold checkbox visibility
[vlc] / modules / video_output / vmem.c
index f1c3fb4c68c47b45aa877f7d2bee070cbe0e8824..3f117da1fa41c0f185371d87d1366200baaceb9b 100644 (file)
@@ -1,24 +1,24 @@
 /*****************************************************************************
  * vmem.c: memory video driver for vlc
  *****************************************************************************
- * Copyright (C) 2008 the VideoLAN team
- * $Id$
+ * Copyright (C) 2008 VLC authors and VideoLAN
+ * Copyrgiht (C) 2010 RĂ©mi Denis-Courmont
  *
  * Authors: Sam Hocevar <sam@zoy.org>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
@@ -86,21 +86,56 @@ struct picture_sys_t {
     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 *opaque;
+    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           Prepare(vout_display_t *, picture_t *, subpicture_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 *);
+static void Lock(void *data, picture_t *pic)
+{
+    vout_display_sys_t *sys = data;
+    picture_sys_t *picsys = pic->p_sys;
+    void *planes[PICTURE_PLANE_MAX];
+
+    picsys->id = sys->lock(sys->opaque, planes);
+
+    for (int i = 0; i < pic->i_planes; i++)
+        pic->p[i].p_pixels = planes[i];
+}
+
+static void Unlock(void *data, picture_t *pic)
+{
+    vout_display_sys_t *sys = data;
+    picture_sys_t *picsys = pic->p_sys;
+    void *planes[PICTURE_PLANE_MAX];
+
+    assert(!picture_IsReferenced(pic));
+
+    for (int i = 0; i < pic->i_planes; i++)
+        planes[i] = pic->p[i].p_pixels;
+
+    if (sys->unlock != NULL)
+        sys->unlock(sys->opaque, picsys->id, planes);
+
+}
 
 /*****************************************************************************
  * Open: allocates video thread
@@ -110,25 +145,75 @@ 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_InheritString(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;
 
-    /* */
-    video_format_t fmt = vd->fmt;
+    /* Define the video format */
+    video_format_t fmt;
+    video_format_ApplyRotation(&fmt, &vd->fmt);
+
+    if (setup != NULL) {
+        char chroma[5];
 
-    fmt.i_chroma = chroma;
-    fmt.i_width  = var_InheritInteger(vd, "vmem-width");
-    fmt.i_height = var_InheritInteger(vd, "vmem-height");
+        memcpy(chroma, &fmt.i_chroma, 4);
+        chroma[4] = '\0';
+        memset(sys->pitches, 0, sizeof(sys->pitches));
+        memset(sys->lines, 0, sizeof(sys->lines));
+
+        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;
+    }
+    fmt.i_x_offset = fmt.i_y_offset = 0;
+    fmt.i_visible_width = fmt.i_width;
+    fmt.i_visible_height = fmt.i_height;
+
+    if (!fmt.i_chroma) {
+        msg_Err(vd, "vmem-chroma should be 4 characters long");
+        free(sys);
+        return VLC_EGENERIC;
+    }
 
     /* Define the bitmasks */
-    switch (chroma)
+    switch (fmt.i_chroma)
     {
     case VLC_CODEC_RGB15:
         fmt.i_rmask = 0x001f;
@@ -141,10 +226,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;
@@ -157,75 +238,24 @@ static int Open(vlc_object_t *object)
         break;
     }
 
-    /* */
-    vout_display_sys_t *sys;
-    vd->sys = sys = calloc(1, sizeof(*sys));
-    if (unlikely(!sys))
-        return VLC_ENOMEM;
-
-    sys->lock = var_InheritAddress(vd, "vmem-lock");
-    if (sys->lock == NULL) {
-        msg_Err(vd, "Invalid lock callback");
-        free(sys);
-        return VLC_EGENERIC;
-    }
-    sys->unlock = var_InheritAddress(vd, "vmem-unlock");
-    sys->display = var_InheritAddress(vd, "vmem-display");
-    sys->opaque = var_InheritAddress(vd, "vmem-data");
-
-    /* */
-    const int pitch = var_InheritInteger(vd, "vmem-pitch");
-    picture_resource_t rsc;
-    rsc.p_sys = malloc(sizeof(*rsc.p_sys));
-    if(unlikely(!rsc.p_sys)) {
-        free(sys);
-        return VLC_ENOMEM;
-    }
-    rsc.p_sys->sys = sys;
-    rsc.p_sys->id = NULL;
-    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_EGENERIC;
-    }
-
     /* */
     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->prepare = Prepare;
     vd->display = Display;
     vd->control = Control;
-    vd->manage  = Manage;
+    vd->manage  = NULL;
 
     /* */
     vout_display_SendEventFullscreen(vd, false);
-    vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height, false);
+    vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height);
+    vout_display_DeleteWindow(vd, NULL);
     return VLC_SUCCESS;
 }
 
@@ -234,74 +264,85 @@ static void Close(vlc_object_t *object)
     vout_display_t *vd = (vout_display_t *)object;
     vout_display_sys_t *sys = vd->sys;
 
-    picture_pool_Delete(sys->pool);
+    if (sys->cleanup)
+        sys->cleanup(sys->opaque);
+
+    picture_pool_Enum(sys->pool, Unlock, sys);
+    picture_pool_Release(sys->pool);
     free(sys);
 }
 
-/* */
 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
-{
-    VLC_UNUSED(count);
-    return vd->sys->pool;
-}
-
-static void Display(vout_display_t *vd, picture_t *picture)
 {
     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);
-}
-
-static int Control(vout_display_t *vd, int query, va_list args)
-{
-    switch (query) {
-    case VOUT_DISPLAY_CHANGE_FULLSCREEN:
-    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: {
-        const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);
-        if (cfg->display.width  != vd->fmt.i_width ||
-            cfg->display.height != vd->fmt.i_height)
-            return VLC_EGENERIC;
-        if (cfg->is_fullscreen)
-            return VLC_EGENERIC;
-        return VLC_SUCCESS;
+    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_sys_t *picsys = malloc(sizeof (*picsys));
+        if (unlikely(picsys == NULL))
+        {
+            count = i;
+            break;
+        }
+        picsys->sys = sys;
+        picsys->id = NULL;
+
+        picture_resource_t rsc = { .p_sys = picsys };
+
+        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;
+        }
     }
-    default:
-        return VLC_EGENERIC;
+
+    /* */
+    sys->pool = picture_pool_New(count, pictures);
+    if (!sys->pool) {
+        for (unsigned i = 0; i < count; i++)
+            picture_Release(pictures[i]);
     }
+
+    picture_pool_Enum(sys->pool, Lock, sys);
+    return sys->pool;
 }
-static void Manage(vout_display_t *vd)
+
+static void Prepare(vout_display_t *vd, picture_t *pic, subpicture_t *subpic)
 {
-    VLC_UNUSED(vd);
+    Unlock(vd->sys, pic);
+    VLC_UNUSED(subpic);
 }
 
-/* */
-static int Lock(picture_t *picture)
-{
-    picture_sys_t *picsys = picture->p_sys;
-    vout_display_sys_t *sys = picsys->sys;
-    void *planes[PICTURE_PLANE_MAX];
 
-    picsys->id = sys->lock(sys->opaque, planes);
+static void Display(vout_display_t *vd, picture_t *pic, subpicture_t *subpic)
+{
+    vout_display_sys_t *sys = vd->sys;
 
-    for (int i = 0; i < picture->i_planes; i++)
-        picture->p[i].p_pixels = planes[i];
+    if (sys->display != NULL)
+        sys->display(sys->opaque, pic->p_sys->id);
 
-    return VLC_SUCCESS;
+    Lock(sys, pic);
+    picture_Release(pic);
+    VLC_UNUSED(subpic);
 }
 
-static void Unlock(picture_t *picture)
+static int Control(vout_display_t *vd, int query, va_list args)
 {
-    picture_sys_t *picsys = picture->p_sys;
-    vout_display_sys_t *sys = picsys->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);
+    (void) vd; (void) query; (void) args;
+    return VLC_EGENERIC;
 }