[vlc-devel] [PATCH 3/3] snapshot: fix copy of opaque pictures

Thomas Guillem thomas at gllm.fr
Mon Jun 5 16:22:06 CEST 2017


Call picture_Copy() only for CPU pictures (planes_count > 0). Otherwise,
convert the opaque picture to a cpu picture.
---
 src/video_output/snapshot.c     | 67 ++++++++++++++++++++++++++++++++++++++---
 src/video_output/snapshot.h     |  3 +-
 src/video_output/video_output.c |  2 +-
 3 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/src/video_output/snapshot.c b/src/video_output/snapshot.c
index 3f48541f56..c5fd7134dd 100644
--- a/src/video_output/snapshot.c
+++ b/src/video_output/snapshot.c
@@ -37,6 +37,7 @@
 #include <vlc_strings.h>
 #include <vlc_block.h>
 #include <vlc_vout.h>
+#include <vlc_filter.h>
 
 #include "snapshot.h"
 #include "vout_internal.h"
@@ -110,17 +111,73 @@ bool vout_snapshot_IsRequested(vout_snapshot_t *snap)
     }
     return has_request;
 }
-void vout_snapshot_Set(vout_snapshot_t *snap,
-                       const picture_t *picture)
+
+static picture_t *filter_chain_buffer_new_cb(filter_t *filter)
+{
+    return picture_NewFromFormat(&filter->fmt_out.video);
+}
+
+static picture_t *snapshot_Copy(vlc_object_t *obj, picture_t *picture)
+{
+    const video_format_t *fmt = &picture->format;
+    const vlc_chroma_description_t *desc =
+        vlc_fourcc_GetChromaDescription(fmt->i_chroma);
+    assert(desc);
+
+    if (desc->plane_count != 0)
+    {
+        /* CPU picture case */
+        picture_t *dup = picture_NewFromFormat(fmt);
+        if (!dup)
+            return NULL;
+        picture_Copy(dup, picture);
+        return dup;
+    }
+
+    /* Create a CPU picture from an Opaque one using a video converter */
+    static const filter_owner_t owner = {
+        .video = {
+            .buffer_new = filter_chain_buffer_new_cb,
+        },
+    };
+    filter_chain_t *chain = filter_chain_NewVideo(obj, true, &owner);
+    if (unlikely(chain == NULL))
+        return NULL;
+
+    es_format_t fmt_in;
+    es_format_InitFromVideo(&fmt_in, fmt);
+
+    /* Set chroma to 0: the video chain converter will find the best available
+     * chroma */
+    es_format_t fmt_out = fmt_in;
+    fmt_out.video.i_chroma = fmt_out.i_codec = 0;
+
+    filter_chain_Reset(chain, &fmt_in, &fmt_out);
+    es_format_Clean(&fmt_in);
+
+    if (filter_chain_AppendConverter(chain, NULL, NULL) != 0)
+    {
+        filter_chain_Delete(chain);
+        return NULL;
+    }
+
+    /* Hold current picture since the filter will release it */
+    picture_Hold(picture);
+    picture_t *dup = filter_chain_VideoFilter(chain, picture);
+    filter_chain_Delete(chain);
+    return dup;
+
+}
+
+void vout_snapshot_Set(vout_snapshot_t *snap, vlc_object_t *obj,
+                       picture_t *picture)
 {
     vlc_mutex_lock(&snap->lock);
     while (snap->request_count > 0) {
-        picture_t *dup = picture_NewFromFormat(&picture->format);
+        picture_t *dup = snapshot_Copy(obj, picture);
         if (!dup)
             break;
 
-        picture_Copy(dup, picture);
-
         dup->p_next = snap->picture;
         snap->picture = dup;
         snap->request_count--;
diff --git a/src/video_output/snapshot.h b/src/video_output/snapshot.h
index 1b361beec2..8254de2576 100644
--- a/src/video_output/snapshot.h
+++ b/src/video_output/snapshot.h
@@ -33,7 +33,6 @@ typedef struct {
     bool        is_available;
     int         request_count;
     picture_t   *picture;
-
 } vout_snapshot_t;
 
 /* */
@@ -55,7 +54,7 @@ bool vout_snapshot_IsRequested(vout_snapshot_t *);
  *
  * The given picture is only copied and not released.
  */
-void vout_snapshot_Set(vout_snapshot_t *, const picture_t *);
+void vout_snapshot_Set(vout_snapshot_t *, vlc_object_t *, picture_t *);
 
 /**
  * This function will return the directory used for snapshots
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index bbd25b631e..fe05beb64c 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -1087,7 +1087,7 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
      * Take a snapshot if requested
      */
     if (do_snapshot)
-        vout_snapshot_Set(&vout->p->snapshot, todisplay);
+        vout_snapshot_Set(&vout->p->snapshot, VLC_OBJECT(vout), todisplay);
 
     /* Render the direct buffer */
     vout_UpdateDisplaySourceProperties(vd, &todisplay->format);
-- 
2.11.0



More information about the vlc-devel mailing list