emtoion gst1 - workaround gst break between 1.10 and 1.12
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>
Wed, 19 Jul 2017 01:44:23 +0000 (10:44 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Wed, 19 Jul 2017 02:07:47 +0000 (11:07 +0900)
so emotion was using a much older (pre 1.0) buffer map mechanism for
getting video data. a new frame map api was added to gst in 1.0 but we
didnt use it. gst broke the old buffer direct mapping for some codecs
paths between 1.10 and 1.12. since we were using a very old method/api
this broke us. this also happens to fix some vaapi issues (except
where the buffer is simply never mappable ever). so this is kind of a
fix (updating us to as more modern api) and a workaround.

@fix

src/modules/emotion/gstreamer1/emotion_alloc.c
src/modules/emotion/gstreamer1/emotion_convert.c
src/modules/emotion/gstreamer1/emotion_gstreamer.h
src/modules/emotion/gstreamer1/emotion_sink.c

index ea85e6c..26a1ec3 100644 (file)
@@ -6,7 +6,7 @@
 
 Emotion_Gstreamer_Buffer *
 emotion_gstreamer_buffer_alloc(EmotionVideoSink *sink,
-                              GstBuffer *buffer,
+                               GstBuffer *buffer,
                                GstVideoInfo *info,
                                Evas_Colorspace eformat,
                                int eheight,
@@ -16,16 +16,19 @@ emotion_gstreamer_buffer_alloc(EmotionVideoSink *sink,
 
    if (!sink->priv->emotion_object) return NULL;
 
-   send = malloc(sizeof (Emotion_Gstreamer_Buffer));
+   send = calloc(1, sizeof(Emotion_Gstreamer_Buffer));
    if (!send) return NULL;
 
    send->sink = gst_object_ref(sink);
    send->frame = gst_buffer_ref(buffer);
    send->info = *info;
+   if (gst_video_frame_map(&(send->vframe), info, buffer, GST_MAP_READ))
+     send->vfmapped = EINA_TRUE;
+   else
+     send->vfmapped = EINA_FALSE;
    send->eformat = eformat;
    send->eheight = eheight;
    send->func = func;
-
    return send;
 }
 
@@ -39,7 +42,7 @@ emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send)
 
 Emotion_Gstreamer_Message *
 emotion_gstreamer_message_alloc(Emotion_Gstreamer *ev,
-                               GstMessage *msg)
+                                GstMessage *msg)
 {
    Emotion_Gstreamer_Message *send;
 
index 97203f8..8ee4399 100644 (file)
@@ -6,7 +6,8 @@
 
 static inline void
 _evas_video_bgrx_step(unsigned char *evas_data, const unsigned char *gst_data,
-                      unsigned int w, unsigned int h EINA_UNUSED, unsigned int output_height, unsigned int step)
+                      unsigned int w, unsigned int h EINA_UNUSED,
+                      unsigned int output_height, unsigned int step)
 {
    unsigned int x, y;
 
@@ -25,7 +26,9 @@ _evas_video_bgrx_step(unsigned char *evas_data, const unsigned char *gst_data,
 }
 
 static void
-_evas_video_bgr(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
+_evas_video_bgr(unsigned char *evas_data, const unsigned char *gst_data,
+                unsigned int w, unsigned int h, unsigned int output_height,
+                Emotion_Convert_Info *info EINA_UNUSED)
 {
    // XXX: need to check offset and stride that gst provide and what they
    // mean with a non-planar format like bgra
@@ -33,7 +36,9 @@ _evas_video_bgr(unsigned char *evas_data, const unsigned char *gst_data, unsigne
 }
 
 static void
-_evas_video_bgrx(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
+_evas_video_bgrx(unsigned char *evas_data, const unsigned char *gst_data,
+                 unsigned int w, unsigned int h, unsigned int output_height,
+                 Emotion_Convert_Info *info EINA_UNUSED)
 {
    // XXX: need to check offset and stride that gst provide and what they
    // mean with a non-planar format like bgra
@@ -41,7 +46,10 @@ _evas_video_bgrx(unsigned char *evas_data, const unsigned char *gst_data, unsign
 }
 
 static void
-_evas_video_bgra(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
+_evas_video_bgra(unsigned char *evas_data, const unsigned char *gst_data,
+                 unsigned int w, unsigned int h EINA_UNUSED,
+                 unsigned int output_height,
+                 Emotion_Convert_Info *info EINA_UNUSED)
 {
    unsigned int x, y;
 
@@ -65,51 +73,70 @@ _evas_video_bgra(unsigned char *evas_data, const unsigned char *gst_data, unsign
 }
 
 static void
-_evas_video_i420(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w EINA_UNUSED, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
+_evas_video_i420(unsigned char *evas_data,
+                 const unsigned char *gst_data EINA_UNUSED,
+                 unsigned int w EINA_UNUSED, unsigned int h EINA_UNUSED,
+                 unsigned int output_height,
+                 Emotion_Convert_Info *info)
 {
    const unsigned char **rows, *ptr;
    unsigned int i, j, jump, rh;
 
+   if (info->bpp[0] != 1) ERR("Plane 0 bpp != 1");
+   if (info->bpp[1] != 1) ERR("Plane 1 bpp != 1");
+   if (info->bpp[2] != 1) ERR("Plane 2 bpp != 1");
+
    rh = output_height;
    rows = (const unsigned char **)evas_data;
 
-   ptr = gst_data + info->plane_offset[0];
+   ptr = info->plane_ptr[0];
    jump = info->stride[0];
    for (i = 0; i < rh; i++, ptr += jump) rows[i] = ptr;
 
-   ptr = gst_data + info->plane_offset[1];
+   ptr = info->plane_ptr[1];
    jump = info->stride[1];
    for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
 
-   ptr = gst_data + info->plane_offset[2];
+   ptr = info->plane_ptr[2];
    jump = info->stride[2];
    for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
 }
 
 static void
-_evas_video_yv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w EINA_UNUSED, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
+_evas_video_yv12(unsigned char *evas_data,
+                 const unsigned char *gst_data EINA_UNUSED,
+                 unsigned int w EINA_UNUSED, unsigned int h EINA_UNUSED,
+                 unsigned int output_height,
+                 Emotion_Convert_Info *info)
 {
    const unsigned char **rows, *ptr;
    unsigned int i, j, jump, rh;
 
+   if (info->bpp[0] != 1) ERR("Plane 0 bpp != 1");
+   if (info->bpp[1] != 1) ERR("Plane 1 bpp != 1");
+   if (info->bpp[2] != 1) ERR("Plane 2 bpp != 1");
+
    rh = output_height;
    rows = (const unsigned char **)evas_data;
 
-   ptr = gst_data + info->plane_offset[0];
+   ptr = info->plane_ptr[0];
    jump = info->stride[0];
    for (i = 0; i < rh; i++, ptr += jump) rows[i] = ptr;
 
-   ptr = gst_data + info->plane_offset[2];
+   ptr = info->plane_ptr[1];
    jump = info->stride[1];
    for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
 
-   ptr = gst_data + info->plane_offset[1];
+   ptr = info->plane_ptr[2];
    jump = info->stride[2];
    for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
 }
 
 static void
-_evas_video_yuy2(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
+_evas_video_yuy2(unsigned char *evas_data, const unsigned char *gst_data,
+                 unsigned int w, unsigned int h EINA_UNUSED,
+                 unsigned int output_height,
+                 Emotion_Convert_Info *info EINA_UNUSED)
 {
    const unsigned char **rows;
    unsigned int i, stride;
@@ -124,19 +151,26 @@ _evas_video_yuy2(unsigned char *evas_data, const unsigned char *gst_data, unsign
 }
 
 static void
-_evas_video_nv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w EINA_UNUSED, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info)
+_evas_video_nv12(unsigned char *evas_data,
+                 const unsigned char *gst_data EINA_UNUSED,
+                 unsigned int w EINA_UNUSED, unsigned int h EINA_UNUSED,
+                 unsigned int output_height, Emotion_Convert_Info *info)
 {
    const unsigned char **rows, *ptr;
    unsigned int i, j, jump, rh;
 
+   if (info->bpp[0] != 1) ERR("Plane 0 bpp != 1");
+   // XXX: not sure this should be 1 but 2 bytes per pixel... no?
+   //if (info->bpp[1] != 1) ERR("Plane 1 bpp != 1");
+
    rh = output_height;
    rows = (const unsigned char **)evas_data;
 
-   ptr = gst_data + info->plane_offset[0];
+   ptr = info->plane_ptr[0];
    jump = info->stride[0];
    for (i = 0; i < rh; i++, ptr += jump) rows[i] = ptr;
 
-   ptr = gst_data + info->plane_offset[1];
+   ptr = info->plane_ptr[1];
    jump = info->stride[1];
    for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
 }
index d31c3dd..2469ef2 100644 (file)
@@ -39,8 +39,9 @@ typedef struct _Emotion_Gstreamer_Message Emotion_Gstreamer_Message;
 
 struct _Emotion_Convert_Info
 {
+   unsigned int bpp[4];
    unsigned int stride[4];
-   unsigned int plane_offset[4];
+   unsigned char *plane_ptr[4];
 };
 
 struct _Emotion_Gstreamer_Metadata
@@ -121,6 +122,8 @@ struct _EmotionVideoSinkPrivate {
    GstBuffer        *last_buffer;
    GstMapInfo        map_info;
 
+   GstVideoFrame last_vframe;
+
    int frames;
    int flapse;
    double rtime;
@@ -136,18 +139,19 @@ struct _EmotionVideoSinkPrivate {
    // Protected by the buffer mutex
    Eina_Bool unlocked : 1;
    Eina_Bool mapped : 1;
+   Eina_Bool vfmapped : 1;
 };
 
 struct _Emotion_Gstreamer_Buffer
 {
+   GstVideoFrame vframe;
    EmotionVideoSink *sink;
-
    GstBuffer *frame;
-
    GstVideoInfo info;
+   Evas_Video_Convert_Cb func;
    Evas_Colorspace eformat;
    int eheight;
-   Evas_Video_Convert_Cb func;
+   Eina_Bool vfmapped : 1;
 };
 
 struct _Emotion_Gstreamer_Message
index a6ccf5b..eaa7d77 100644 (file)
@@ -137,15 +137,28 @@ emotion_video_sink_dispose(GObject* object)
    sink = EMOTION_VIDEO_SINK(object);
    priv = sink->priv;
 
-   if ((priv->mapped) && (priv->last_buffer))
+   if (priv->vfmapped)
      {
         if (priv->evas_object)
           {
              evas_object_image_size_set(priv->evas_object, 1, 1);
              evas_object_image_data_set(priv->evas_object, NULL);
           }
-        gst_buffer_unmap(priv->last_buffer, &(priv->map_info));
-        priv->mapped = EINA_FALSE;
+        gst_video_frame_unmap(&(priv->last_vframe));
+        priv->vfmapped = EINA_FALSE;
+     }
+   else
+     {
+        if ((priv->mapped) && (priv->last_buffer))
+          {
+             if (priv->evas_object)
+               {
+                  evas_object_image_size_set(priv->evas_object, 1, 1);
+                  evas_object_image_data_set(priv->evas_object, NULL);
+               }
+             gst_buffer_unmap(priv->last_buffer, &(priv->map_info));
+             priv->mapped = EINA_FALSE;
+          }
      }
    if (priv->last_buffer)
      {
@@ -231,6 +244,16 @@ emotion_video_sink_stop(GstBaseSink* base_sink)
    INF("sink stop");
 
    eina_lock_take(&priv->m);
+   if (priv->vfmapped)
+     {
+        if (priv->evas_object)
+          {
+             evas_object_image_size_set(priv->evas_object, 1, 1);
+             evas_object_image_data_set(priv->evas_object, NULL);
+          }
+        gst_video_frame_unmap(&(priv->last_vframe));
+        priv->vfmapped = EINA_FALSE;
+     }
    if (priv->last_buffer)
      {
         if (priv->evas_object)
@@ -401,10 +424,13 @@ emotion_video_sink_main_render(void *data)
 
    buffer = gst_buffer_ref(send->frame);
 
-   if (!gst_buffer_map(buffer, &map, GST_MAP_READ))
+   if (!send->vfmapped)
      {
-        ERR("Cannot map video buffer for read.\n");
-        goto exit_point;
+        if (!gst_buffer_map(buffer, &map, GST_MAP_READ))
+          {
+             ERR("Cannot map video buffer for read.\n");
+             goto exit_point;
+          }
      }
 
    INF("sink main render [%i, %i] (source height: %i)", send->info.width, send->eheight, send->info.height);
@@ -434,14 +460,39 @@ emotion_video_sink_main_render(void *data)
    info.plane_offset[2] = send->info.offset[2];
    info.plane_offset[3] = send->info.offset[3];
  */
-   info.stride[0] = send->info.stride[0];
-   info.stride[1] = send->info.stride[1];
-   info.stride[2] = send->info.stride[2];
-   info.stride[3] = send->info.stride[3];
-   info.plane_offset[0] = send->info.offset[0];
-   info.plane_offset[1] = send->info.offset[1];
-   info.plane_offset[2] = send->info.offset[2];
-   info.plane_offset[3] = send->info.offset[3];
+   if (send->vfmapped)
+     {
+        GstVideoFrame *vframe = &(send->vframe);
+
+        map.data = GST_VIDEO_FRAME_PLANE_DATA(vframe, 0);
+        info.bpp[0] = GST_VIDEO_FRAME_COMP_PSTRIDE(vframe, 0);
+        info.bpp[1] = GST_VIDEO_FRAME_COMP_PSTRIDE(vframe, 1);
+        info.bpp[2] = GST_VIDEO_FRAME_COMP_PSTRIDE(vframe, 2);
+        info.bpp[3] = GST_VIDEO_FRAME_COMP_PSTRIDE(vframe, 3);
+        info.stride[0] = GST_VIDEO_FRAME_COMP_STRIDE(vframe, 0);
+        info.stride[1] = GST_VIDEO_FRAME_COMP_STRIDE(vframe, 1);
+        info.stride[2] = GST_VIDEO_FRAME_COMP_STRIDE(vframe, 2);
+        info.stride[3] = GST_VIDEO_FRAME_COMP_STRIDE(vframe, 3);
+        info.plane_ptr[0] = GST_VIDEO_FRAME_PLANE_DATA(vframe, 0);
+        info.plane_ptr[1] = GST_VIDEO_FRAME_PLANE_DATA(vframe, 1);
+        info.plane_ptr[2] = GST_VIDEO_FRAME_PLANE_DATA(vframe, 2);
+        info.plane_ptr[3] = GST_VIDEO_FRAME_PLANE_DATA(vframe, 3);
+     }
+   else
+     {
+        info.bpp[0] = 1;
+        info.bpp[1] = 1;
+        info.bpp[2] = 1;
+        info.bpp[3] = 1;
+        info.stride[0] = send->info.stride[0];
+        info.stride[1] = send->info.stride[1];
+        info.stride[2] = send->info.stride[2];
+        info.stride[3] = send->info.stride[3];
+        info.plane_ptr[0] = ((unsigned char *)map.data) + send->info.offset[0];
+        info.plane_ptr[1] = ((unsigned char *)map.data) + send->info.offset[1];
+        info.plane_ptr[2] = ((unsigned char *)map.data) + send->info.offset[2];
+        info.plane_ptr[3] = ((unsigned char *)map.data) + send->info.offset[3];
+     }
 
    if (send->func)
      send->func(evas_data, map.data, send->info.width, send->info.height, send->eheight, &info);
@@ -459,10 +510,26 @@ emotion_video_sink_main_render(void *data)
 
    _emotion_frame_resize(priv->emotion_object, send->info.width, send->eheight, ratio);
 
-   if ((priv->mapped) && (priv->last_buffer))
-     gst_buffer_unmap(priv->last_buffer, &(priv->map_info));
-   priv->map_info = map;
-   priv->mapped = EINA_TRUE;
+   if (priv->vfmapped)
+     {
+        gst_video_frame_unmap(&(priv->last_vframe));
+     }
+   else
+     {
+        if ((priv->mapped) && (priv->last_buffer))
+          gst_buffer_unmap(priv->last_buffer, &(priv->map_info));
+     }
+   if (send->vfmapped)
+     {
+        priv->last_vframe = send->vframe;
+        priv->vfmapped = EINA_TRUE;
+     }
+   else
+     {
+        priv->vfmapped = EINA_FALSE;
+        priv->map_info = map;
+        priv->mapped = EINA_TRUE;
+     }
 
    if (priv->last_buffer) gst_buffer_unref(priv->last_buffer);
    priv->last_buffer = buffer;