[vlc-commits] vout: refresh EPG OSD

Francois Cartegnie git at videolan.org
Wed Sep 27 15:57:53 CEST 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Tue May 30 17:42:19 2017 +0200| [f25cc7fb4c732184db80543d045f29bdeec70de3] | committer: Francois Cartegnie

vout: refresh EPG OSD

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f25cc7fb4c732184db80543d045f29bdeec70de3
---

 src/Makefile.am                          |   1 +
 src/video_output/video_epg.c             | 392 +++++++++++++++++++++++++------
 src/video_output/vout_spuregion_helper.h |  94 ++++++++
 3 files changed, 411 insertions(+), 76 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 9712483bb8..87ea540f69 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -287,6 +287,7 @@ libvlccore_la_SOURCES = \
 	video_output/video_epg.c \
 	video_output/video_widgets.c \
 	video_output/vout_subpictures.c \
+	video_output/vout_spuregion_helper.h \
 	video_output/window.c \
 	video_output/window.h \
 	video_output/opengl.c \
diff --git a/src/video_output/video_epg.c b/src/video_output/video_epg.c
index 7eb1cc8b9b..9576eb0682 100644
--- a/src/video_output/video_epg.c
+++ b/src/video_output/video_epg.c
@@ -2,6 +2,7 @@
  * video_epg.c : EPG manipulation functions
  *****************************************************************************
  * Copyright (C) 2010 Adrien Maglo
+ *               2017 VLC authors, VideoLAN and VideoLabs
  *
  * Author: Adrien Maglo <magsoft at videolan.org>
  *
@@ -32,13 +33,32 @@
 #include <vlc_events.h>
 #include <vlc_input_item.h>
 #include <vlc_epg.h>
+#include <vlc_url.h>
+#include "vout_spuregion_helper.h"
 
 /* Layout percentage defines */
-#define EPG_TOP 0.7
-#define EPG_LEFT 0.1
-#define EPG_NAME_SIZE 0.05
-#define EPG_PROGRAM_SIZE 0.03
-#define EPG_TIME_SIZE 0.03
+#define OSDEPG_MARGIN   0.025
+#define OSDEPG_MARGINS  (OSDEPG_MARGIN * 2)
+#define OSDEPG_PADDING  0.05 /* inner margins */
+#define OSDEPG_WIDTH    (1.0 - OSDEPG_MARGINS)
+#define OSDEPG_HEIGHT   0.25
+#define OSDEPG_LEFT     OSDEPG_MARGIN
+#define OSDEPG_TOP      (1.0 - OSDEPG_MARGINS - OSDEPG_HEIGHT + OSDEPG_MARGIN)
+
+/* layout */
+#define OSDEPG_ROWS_COUNT  10
+#define OSDEPG_ROW_HEIGHT  (1.0 / OSDEPG_ROWS_COUNT)
+#define OSDEPG_LOGO_SIZE (OSDEPG_HEIGHT)
+
+/* shortcuts */
+#define OSDEPG_RIGHT    (1.0 - OSDEPG_MARGIN)
+
+#define OSDEPG_ROWS(x)  (OSDEPG_ROW_HEIGHT * x)
+#define OSDEPG_ROW(x)   (OSDEPG_ROWS(x))
+
+#define EPGOSD_TEXTSIZE_NAME    (OSDEPG_ROWS(2))
+#define EPGOSD_TEXTSIZE_PROG    (OSDEPG_ROWS(2))
+#define EPGOSD_TEXTSIZE_NTWK    (OSDEPG_ROWS(2))
 
 #define RGB2YUV( R, G, B ) \
     ((0.257 * R) + (0.504 * G) + (0.098 * B) + 16), \
@@ -48,6 +68,65 @@
 #define HEX2YUV( rgb ) \
     RGB2YUV( (rgb >> 16), ((rgb & 0xFF00) >> 8), (rgb & 0xFF) )
 
+//#define RGB_COLOR1   0xf48b00
+//#define ARGB_BGCOLOR 0xC0333333
+
+#define RGB_COLOR1   0x2badde
+#define ARGB_BGCOLOR 0xc003182d
+
+struct subpicture_updater_sys_t
+{
+    vlc_epg_t *epg;
+    int64_t    time;
+    char      *art;
+    vlc_object_t *obj;
+};
+
+static char * GetDefaultArtUri( void )
+{
+    char *psz_uri = NULL;
+    char *psz_path;
+    char *psz_datadir = config_GetDataDir();
+    if( asprintf( &psz_path, "%s/icons/128x128/vlc.png", psz_datadir ) >= 0 )
+    {
+        psz_uri = vlc_path2uri( psz_path, NULL );
+        free( psz_path );
+    }
+    free( psz_datadir );
+    return psz_uri;
+}
+
+#define GRADIENT_COLORS 40
+
+static subpicture_region_t * vout_OSDBackground(int x, int y,
+                                                int width, int height,
+                                                uint32_t i_argb)
+{
+    /* Create a new subpicture region */
+    video_palette_t palette;
+    spuregion_CreateVGradientPalette( &palette, GRADIENT_COLORS, i_argb, 0xFF000000 );
+
+    video_format_t fmt;
+    video_format_Init(&fmt, VLC_CODEC_YUVP);
+    fmt.i_width  = fmt.i_visible_width  = width;
+    fmt.i_height = fmt.i_visible_height = height;
+    fmt.i_sar_num = 1;
+    fmt.i_sar_den = 1;
+    fmt.p_palette = &palette;
+
+    subpicture_region_t *region = subpicture_region_New(&fmt);
+    if (!region)
+        return NULL;
+
+    region->i_align = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP;
+    region->i_x = x;
+    region->i_y = y;
+
+    spuregion_CreateVGradientFill( region->p_picture->p, palette.i_entries );
+
+    return region;
+}
+
 static subpicture_region_t * vout_OSDEpgSlider(int x, int y,
                                                int width, int height,
                                                float ratio)
@@ -56,10 +135,10 @@ static subpicture_region_t * vout_OSDEpgSlider(int x, int y,
     video_palette_t palette = {
         .i_entries = 4,
         .palette = {
-            [0] = { HEX2YUV(0xffffff), 0x00 }, /* Bar fill remain/background */
-            [1] = { HEX2YUV(0x000000), 0x00 },
-            [2] = { HEX2YUV(0xffffff), 0xff }, /* Bar fill */
-            [3] = { HEX2YUV(0x000000), 0xff }, /* Bar outline */
+            [0] = { HEX2YUV(RGB_COLOR1), 0x20 }, /* Bar fill remain/background */
+            [1] = { HEX2YUV(0x00ff00), 0xff },
+            [2] = { HEX2YUV(RGB_COLOR1), 0xC0 }, /* Bar fill */
+            [3] = { HEX2YUV(0xffffff), 0xff }, /* Bar outline */
         },
     };
 
@@ -75,6 +154,7 @@ static subpicture_region_t * vout_OSDEpgSlider(int x, int y,
     if (!region)
         return NULL;
 
+    region->i_align = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP;
     region->i_x = x;
     region->i_y = y;
 
@@ -101,6 +181,15 @@ static subpicture_region_t * vout_OSDEpgSlider(int x, int y,
     return region;
 }
 
+static void vout_OSDSegmentSetNoWrap(text_segment_t *p_segment)
+{
+    for( ; p_segment; p_segment = p_segment->p_next )
+    {
+        p_segment->style->e_wrapinfo = STYLE_WRAP_NONE;
+        p_segment->style->i_features |= STYLE_HAS_WRAP_INFO;
+    }
+}
+
 static text_segment_t * vout_OSDSegment(const char *psz_text, int size, uint32_t color)
 {
     text_segment_t *p_segment = text_segment_New(psz_text);
@@ -118,11 +207,43 @@ static text_segment_t * vout_OSDSegment(const char *psz_text, int size, uint32_t
     p_segment->style->i_font_size  = __MAX(size ,1 );
     p_segment->style->i_font_color = color;
     p_segment->style->i_font_alpha = STYLE_ALPHA_OPAQUE;
-    p_segment->style->i_features |= STYLE_HAS_FONT_ALPHA | STYLE_HAS_FONT_COLOR;
+    p_segment->style->i_outline_alpha = STYLE_ALPHA_TRANSPARENT;
+    p_segment->style->i_shadow_alpha = STYLE_ALPHA_TRANSPARENT;
+    p_segment->style->i_features |= STYLE_HAS_FONT_ALPHA | STYLE_HAS_FONT_COLOR |
+                                    STYLE_HAS_OUTLINE_ALPHA | STYLE_HAS_SHADOW_ALPHA;
 
     return p_segment;
 }
 
+static subpicture_region_t * vout_OSDImage( vlc_object_t *p_obj,
+                                            int x, int y, int w, int h,
+                                            const char *psz_uri )
+{
+    video_format_t fmt_out;
+    video_format_Init( &fmt_out, VLC_CODEC_YUVA );
+    fmt_out.i_width = fmt_out.i_visible_width = w;
+    fmt_out.i_height = fmt_out.i_visible_height = h;
+
+    subpicture_region_t *image =
+            spuregion_CreateFromPicture( p_obj, &fmt_out, psz_uri );
+    if( image )
+    {
+        image->i_x = x;
+        image->i_y = y;
+        image->i_align = SUBPICTURE_ALIGN_LEFT|SUBPICTURE_ALIGN_TOP;
+    }
+    return image;
+}
+
+static void vout_OSDRegionConstrain(subpicture_region_t *p_region, int w, int h)
+{
+    if( p_region )
+    {
+        p_region->i_max_width = w;
+        p_region->i_max_height = h;
+    }
+}
+
 static subpicture_region_t * vout_OSDTextRegion(text_segment_t *p_segment,
                                                 int x, int y )
 {
@@ -145,6 +266,7 @@ static subpicture_region_t * vout_OSDTextRegion(text_segment_t *p_segment,
     region->i_align  = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP;
     region->i_x      = x;
     region->i_y      = y;
+    region->b_balanced_text = false;
 
     return region;
 }
@@ -166,91 +288,203 @@ static char * vout_OSDPrintTime(time_t t)
     return psz;
 }
 
-static subpicture_region_t * vout_BuildOSDEpg(vlc_epg_t *epg,
-                                              int64_t epgtime,
-                                              int x, int y,
-                                              int visible_width,
-                                              int visible_height)
+static subpicture_region_t * vout_OSDEpgEvent(const vlc_epg_event_t *p_evt,
+                                              int x, int y, int size)
 {
-    subpicture_region_t *head;
-    subpicture_region_t **last_ptr = &head;
+    text_segment_t *p_segment = NULL;
+    char *psz_start = vout_OSDPrintTime(p_evt->i_start);
+    char *psz_end = vout_OSDPrintTime(p_evt->i_start + p_evt->i_duration);
+    char *psz_text;
+    if( -1 < asprintf(&psz_text, "%s-%s ", psz_start, psz_end))
+    {
+        p_segment = vout_OSDSegment(psz_text, size, RGB_COLOR1);
+        if( p_segment )
+            p_segment->p_next = vout_OSDSegment(p_evt->psz_name, size, 0xffffff);
+        vout_OSDSegmentSetNoWrap( p_segment );
+    }
+    free( psz_start );
+    free( psz_end );
+    if(!p_segment)
+        return NULL;
+    return vout_OSDTextRegion(p_segment, x, y);
+}
 
+static void vout_FillRightPanel(subpicture_updater_sys_t *p_sys,
+                                int x, int y,
+                                int width, int height,
+                                int rx, int ry,
+                                subpicture_region_t **last_ptr)
+{
     float f_progress = 0;
+    VLC_UNUSED(ry);
+
+    /* Format the hours */
+    char *psz_network = vout_OSDPrintTime(p_sys->time);
 
     /* Display the name of the channel. */
-    *last_ptr = vout_OSDEpgText(epg->psz_name,
-                                x + visible_width  * EPG_LEFT,
-                                y + visible_height * EPG_TOP,
-                                visible_height * EPG_NAME_SIZE,
+    *last_ptr = vout_OSDEpgText(p_sys->epg->psz_name,
+                                x,
+                                y,
+                                height * EPGOSD_TEXTSIZE_NAME,
                                 0x00ffffff);
+    if(*last_ptr)
+        last_ptr = &(*last_ptr)->p_next;
 
-    if (!*last_ptr)
-        return head;
+    const vlc_epg_event_t *p_current = p_sys->epg->p_current;
+    vlc_epg_event_t *p_next = NULL;
+    if(!p_sys->epg->p_current && p_sys->epg->i_event)
+        p_current = p_sys->epg->pp_event[0];
+
+    for(size_t i=0; i<p_sys->epg->i_event; i++)
+    {
+        if( p_sys->epg->pp_event[i]->i_id != p_current->i_id )
+        {
+            p_next = p_sys->epg->pp_event[i];
+            break;
+        }
+    }
 
     /* Display the name of the current program. */
-    last_ptr = &(*last_ptr)->p_next;
-    *last_ptr = vout_OSDEpgText(epg->p_current ? epg->p_current->psz_name : NULL,
-                                x + visible_width  * (EPG_LEFT + 0.025),
-                                y + visible_height * (EPG_TOP + 0.05),
-                                visible_height * EPG_PROGRAM_SIZE,
-                                0x00ffffff);
+    if(p_current)
+    {
+        *last_ptr = vout_OSDEpgEvent(p_current,
+                                     x,
+                                     y + height * OSDEPG_ROW(2),
+                                     height * EPGOSD_TEXTSIZE_PROG);
+        /* region rendering limits */
+        vout_OSDRegionConstrain(*last_ptr, width, 0);
+        if(*last_ptr)
+            last_ptr = &(*last_ptr)->p_next;
+    }
 
-    if (!*last_ptr || !epg->p_current)
-        return head;
+    /* NEXT EVENT */
+    if(p_next)
+    {
+        *last_ptr = vout_OSDEpgEvent(p_next,
+                                     x,
+                                     y + height * OSDEPG_ROW(5),
+                                     height * EPGOSD_TEXTSIZE_PROG);
+        /* region rendering limits */
+        vout_OSDRegionConstrain(*last_ptr, width, 0);
+        if(*last_ptr)
+            last_ptr = &(*last_ptr)->p_next;
+    }
 
-    if(epgtime)
+    if(p_sys->time)
     {
-        f_progress = (epgtime - epg->p_current->i_start) /
-                     (float)epg->p_current->i_duration;
+        f_progress = (p_sys->time - p_sys->epg->p_current->i_start) /
+                     (float)p_sys->epg->p_current->i_duration;
     }
 
     /* Display the current program time slider. */
-    last_ptr = &(*last_ptr)->p_next;
-    *last_ptr = vout_OSDEpgSlider(x + visible_width  * EPG_LEFT,
-                                  y + visible_height * (EPG_TOP + 0.1),
-                                  visible_width  * (1 - 2 * EPG_LEFT),
-                                  visible_height * 0.05,
+    *last_ptr = vout_OSDEpgSlider(x + width * 0.05,
+                                  y + height * OSDEPG_ROW(9),
+                                  width  * 0.90,
+                                  height * OSDEPG_ROWS(1),
                                   f_progress);
+    if (*last_ptr)
+        last_ptr = &(*last_ptr)->p_next;
+
+    *last_ptr = vout_OSDEpgText(psz_network,
+                                rx,
+                                y + height * OSDEPG_ROW(0),
+                                height * EPGOSD_TEXTSIZE_NTWK,
+                                RGB_COLOR1);
+    if(*last_ptr)
+    {
+        (*last_ptr)->i_align = SUBPICTURE_ALIGN_TOP|SUBPICTURE_ALIGN_RIGHT;
+        last_ptr = &(*last_ptr)->p_next;
+    }
 
-    if (!*last_ptr)
-        return head;
+    free(psz_network);
+}
 
-    /* Format the hours of the beginning and the end of the current program. */
-    char *psz_start = vout_OSDPrintTime(epg->p_current->i_start);
-    char *psz_end = vout_OSDPrintTime(epg->p_current->i_start +
-                                      epg->p_current->i_duration);
+static subpicture_region_t * vout_BuildOSDEpg(subpicture_updater_sys_t *p_sys,
+                                              int x, int y,
+                                              int visible_width,
+                                              int visible_height)
+{
+    subpicture_region_t *head;
+    subpicture_region_t **last_ptr = &head;
 
-    /* Display those hours. */
-    last_ptr = &(*last_ptr)->p_next;
-    *last_ptr = vout_OSDEpgText(psz_start,
-                                x + visible_width  * (EPG_LEFT + 0.02),
-                                y + visible_height * (EPG_TOP + 0.15),
-                                visible_height * EPG_TIME_SIZE,
-                                0x00ffffff);
+    const int i_padding = visible_height * (OSDEPG_HEIGHT * OSDEPG_PADDING);
 
-    if (!*last_ptr)
-        goto end;
+    *last_ptr = vout_OSDBackground(x + visible_width * OSDEPG_LEFT,
+                                   y + visible_height * OSDEPG_TOP,
+                                   visible_width  * OSDEPG_WIDTH,
+                                   visible_height * OSDEPG_HEIGHT,
+                                   ARGB_BGCOLOR);
+    if(*last_ptr)
+        last_ptr = &(*last_ptr)->p_next;
 
-    last_ptr = &(*last_ptr)->p_next;
-    *last_ptr = vout_OSDEpgText(psz_end,
-                                x + visible_width  * (1 - EPG_LEFT - 0.085),
-                                y + visible_height * (EPG_TOP + 0.15),
-                                visible_height * EPG_TIME_SIZE,
-                                0x00ffffff);
+    struct
+    {
+        int x;
+        int y;
+        int w;
+        int h;
+        int rx;
+        int ry;
+    } panel = {
+        x + visible_width  * OSDEPG_LEFT + i_padding,
+        y + visible_height * OSDEPG_TOP + i_padding,
+        visible_width  * OSDEPG_WIDTH - 2 * i_padding,
+        visible_height * OSDEPG_HEIGHT - 2 * i_padding,
+        visible_width * OSDEPG_LEFT + i_padding,
+        visible_height * (1.0 - OSDEPG_TOP - OSDEPG_HEIGHT) + i_padding,
+    };
+
+
+    if( p_sys->art )
+    {
+        struct
+        {
+            int x;
+            int y;
+            int w;
+            int h;
+        } logo = {
+            panel.x,
+            panel.y,
+            panel.h,
+            panel.h,
+        };
+
+        *last_ptr = vout_OSDBackground(logo.x,
+                                       logo.y,
+                                       logo.w,
+                                       logo.h,
+                                       0xFF000000 | RGB_COLOR1);
+        if(*last_ptr)
+            last_ptr = &(*last_ptr)->p_next;
+
+        int logo_padding = visible_height * (OSDEPG_LOGO_SIZE * OSDEPG_PADDING);
+        *last_ptr = vout_OSDImage( p_sys->obj,
+                                   logo.x + logo_padding,
+                                   logo.y + logo_padding,
+                                   logo.w - 2 * logo_padding,
+                                   logo.h - 2 * logo_padding,
+                                   p_sys->art );
+        if(*last_ptr)
+            last_ptr = &(*last_ptr)->p_next;
+
+        /* shrink */
+        panel.x += logo.w + i_padding;
+        panel.w -= logo.w + i_padding;
+    }
 
-end:
-    free(psz_start);
-    free(psz_end);
+    vout_FillRightPanel( p_sys,
+                         panel.x,
+                         panel.y,
+                         panel.w,
+                         panel.h,
+                         panel.rx,
+                         panel.ry,
+                         last_ptr );
 
     return head;
 }
 
-struct subpicture_updater_sys_t
-{
-    vlc_epg_t *epg;
-    int64_t    time;
-};
-
 static int OSDEpgValidate(subpicture_t *subpic,
                           bool has_src_changed, const video_format_t *fmt_src,
                           bool has_dst_changed, const video_format_t *fmt_dst,
@@ -281,8 +515,7 @@ static void OSDEpgUpdate(subpicture_t *subpic,
     subpic->i_original_picture_width  = fmt.i_visible_width;
     subpic->i_original_picture_height = fmt.i_visible_height;
 
-    subpic->p_region = vout_BuildOSDEpg(sys->epg,
-                                        sys->time,
+    subpic->p_region = vout_BuildOSDEpg(sys,
                                         fmt.i_x_offset,
                                         fmt.i_y_offset,
                                         fmt.i_visible_width,
@@ -292,8 +525,9 @@ static void OSDEpgUpdate(subpicture_t *subpic,
 static void OSDEpgDestroy(subpicture_t *subpic)
 {
     subpicture_updater_sys_t *sys = subpic->updater.p_sys;
-
-    vlc_epg_Delete(sys->epg);
+    if( sys->epg )
+        vlc_epg_Delete(sys->epg);
+    free( sys->art );
     free(sys);
 }
 
@@ -301,14 +535,14 @@ static void OSDEpgDestroy(subpicture_t *subpic)
  * \brief Show EPG information about the current program of an input item
  * \param vout pointer to the vout the information is to be showed on
  * \param p_input pointer to the input item the information is to be showed
+ * \param i_action osd_epg_action_e action
  */
-int vout_OSDEpg(vout_thread_t *vout, input_item_t *input)
+int vout_OSDEpg(vout_thread_t *vout, input_item_t *input )
 {
     vlc_epg_t *epg = NULL;
     int64_t epg_time;
 
     /* Look for the current program EPG event */
-
     vlc_mutex_lock(&input->lock);
 
     const vlc_epg_t *tmp = input->p_epg_table;
@@ -378,7 +612,12 @@ int vout_OSDEpg(vout_thread_t *vout, input_item_t *input)
         return VLC_EGENERIC;
     }
     sys->epg = epg;
+    sys->obj = VLC_OBJECT(vout);
     sys->time = epg_time;
+    sys->art = input_item_GetMeta( input, vlc_meta_ArtworkURL );
+    if( !sys->art )
+        sys->art = GetDefaultArtUri();
+
     subpicture_updater_t updater = {
         .pf_validate = OSDEpgValidate,
         .pf_update   = OSDEpgUpdate,
@@ -398,8 +637,9 @@ int vout_OSDEpg(vout_thread_t *vout, input_item_t *input)
     subpic->i_start    = now;
     subpic->i_stop     = now + 3000 * INT64_C(1000);
     subpic->b_ephemer  = true;
-    subpic->b_absolute = true;
+    subpic->b_absolute = false;
     subpic->b_fade     = true;
+    subpic->b_subtitle = false;
 
     vout_PutSubpicture(vout, subpic);
 
diff --git a/src/video_output/vout_spuregion_helper.h b/src/video_output/vout_spuregion_helper.h
new file mode 100644
index 0000000000..9738e35ecd
--- /dev/null
+++ b/src/video_output/vout_spuregion_helper.h
@@ -0,0 +1,94 @@
+/*****************************************************************************
+ * vout_spuregion_helper.h : vout subpicture region helpers
+ *****************************************************************************
+ * Copyright (C) 2017 VLC authors, VideoLAN and VideoLabs
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * 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.
+ *****************************************************************************/
+#include <vlc_image.h>
+
+#define RGB2YUV( R, G, B ) \
+    ((0.257 * R) + (0.504 * G) + (0.098 * B) + 16), \
+    (-(0.148 * R) - (0.291 * G) + (0.439 * B) + 128),\
+    ((0.439 * R) - (0.368 * G) - (0.071 * B) + 128)
+
+#define HEX2YUV( rgb ) \
+    RGB2YUV( (rgb >> 16), ((rgb & 0xFF00) >> 8), (rgb & 0xFF) )
+
+static inline void
+spuregion_CreateVGradientPalette( video_palette_t *p_palette, uint8_t i_splits,
+                                  uint32_t argb1, uint32_t argb2 )
+{
+    for( uint8_t i = 0; i<i_splits; i++ )
+    {
+        uint32_t rgb1 = argb1 & 0x00FFFFFF;
+        uint32_t rgb2 = argb2 & 0x00FFFFFF;
+
+        uint32_t r = ((((rgb1 >> 16) * (i_splits - i)) + (rgb2 >> 16) * i)) / i_splits;
+        uint32_t g = (((((rgb1 >> 8) & 0xFF) * (i_splits - i)) + ((rgb2 >> 8) & 0xFF) * i)) / i_splits;
+        uint32_t b = ((((rgb1 & 0xFF) * (i_splits - i)) + (rgb2 & 0xFF) * i)) / i_splits;
+        uint8_t entry[4] = { RGB2YUV( r,g,b ), argb1 >> 24 };
+        memcpy( p_palette->palette[i], entry, 4 );
+    }
+    p_palette->i_entries = i_splits;
+}
+
+static inline void
+spuregion_CreateVGradientFill( plane_t *p, uint8_t i_splits )
+{
+    const int i_split = p->i_visible_lines / i_splits;
+    const int i_left = p->i_visible_lines % i_splits + p->i_lines - p->i_visible_lines;
+    for( int i = 0; i<i_splits; i++ )
+    {
+        memset( &p->p_pixels[p->i_pitch * (i * i_split)],
+                i,
+                p->i_pitch * i_split );
+    }
+    memset( &p->p_pixels[p->i_pitch * (i_splits - 1) * i_split],
+            i_splits - 1,
+            p->i_pitch * i_left );
+}
+
+
+static inline subpicture_region_t *
+spuregion_CreateFromPicture( vlc_object_t *p_this, video_format_t *p_fmt,
+                             const char *psz_uri )
+{
+    video_format_t fmt_in;
+    video_format_Init( &fmt_in, 0 );
+
+    picture_t *p_pic = NULL;
+    int i_flags = p_this->obj.flags;
+    p_this->obj.flags |= OBJECT_FLAGS_NOINTERACT|OBJECT_FLAGS_QUIET;
+    image_handler_t *p_image = image_HandlerCreate( p_this );
+    if( p_image )
+    {
+        p_pic = image_ReadUrl( p_image, psz_uri, &fmt_in, p_fmt );
+        image_HandlerDelete( p_image );
+    }
+    p_this->obj.flags = i_flags;
+
+    if(!p_pic)
+        return NULL;
+
+    subpicture_region_t *region = subpicture_region_New(p_fmt);
+    if (!region)
+        return NULL;
+
+    picture_Release( region->p_picture );
+    region->p_picture = p_pic;
+
+    return region;
+}



More information about the vlc-commits mailing list