1 /*****************************************************************************
2 * video_text.c : OSD text manipulation functions
3 *****************************************************************************
4 * Copyright (C) 1999-2010 VLC authors and VideoLAN
5 * $Id: 58566b4ec60c9a6f6493205136008092739d97b9 $
6 *
7 * Author: Sigmund Augdal Helberg <dnumgis@videolan.org>
8 * Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28 #include <assert.h>
29
30 #include <vlc_common.h>
31 #include <vlc_vout.h>
32 #include <vlc_vout_osd.h>
33
34 struct subpicture_updater_sys_t {
35 int position;
36 char *text;
37 };
38
OSDTextValidate(subpicture_t * subpic,bool has_src_changed,const video_format_t * fmt_src,bool has_dst_changed,const video_format_t * fmt_dst,mtime_t ts)39 static int OSDTextValidate(subpicture_t *subpic,
40 bool has_src_changed, const video_format_t *fmt_src,
41 bool has_dst_changed, const video_format_t *fmt_dst,
42 mtime_t ts)
43 {
44 VLC_UNUSED(subpic); VLC_UNUSED(ts);
45 VLC_UNUSED(fmt_src); VLC_UNUSED(has_src_changed);
46 VLC_UNUSED(fmt_dst);
47
48 if( !has_dst_changed )
49 return VLC_SUCCESS;
50 return VLC_EGENERIC;
51 }
52
OSDTextUpdate(subpicture_t * subpic,const video_format_t * fmt_src,const video_format_t * fmt_dst,mtime_t ts)53 static void OSDTextUpdate(subpicture_t *subpic,
54 const video_format_t *fmt_src,
55 const video_format_t *fmt_dst,
56 mtime_t ts)
57 {
58 subpicture_updater_sys_t *sys = subpic->updater.p_sys;
59 VLC_UNUSED(fmt_src); VLC_UNUSED(ts);
60
61 if( fmt_dst->i_sar_num <= 0 || fmt_dst->i_sar_den <= 0 )
62 return;
63
64 subpic->b_absolute = false;
65 subpic->i_original_picture_width = fmt_dst->i_visible_width * fmt_dst->i_sar_num / fmt_dst->i_sar_den;
66 subpic->i_original_picture_height = fmt_dst->i_visible_height;
67
68 video_format_t fmt;
69 video_format_Init( &fmt, VLC_CODEC_TEXT);
70 fmt.i_sar_num = 1;
71 fmt.i_sar_den = 1;
72
73 subpicture_region_t *r = subpic->p_region = subpicture_region_New(&fmt);
74 if (!r)
75 return;
76
77 r->p_text = text_segment_New( sys->text );
78
79 const float margin_ratio = 0.04;
80 const int margin_h = margin_ratio * fmt_dst->i_visible_width;
81 const int margin_v = margin_ratio * fmt_dst->i_visible_height;
82
83 r->i_text_align = sys->position;
84 r->i_align = sys->position;
85 r->i_x = 0;
86 if (r->i_align & SUBPICTURE_ALIGN_LEFT)
87 r->i_x += margin_h + fmt_dst->i_x_offset;
88 else if (r->i_align & SUBPICTURE_ALIGN_RIGHT)
89 r->i_x += margin_h - fmt_dst->i_x_offset;
90
91 r->i_y = 0;
92 if (r->i_align & SUBPICTURE_ALIGN_TOP )
93 r->i_y += margin_v + fmt_dst->i_y_offset;
94 else if (r->i_align & SUBPICTURE_ALIGN_BOTTOM )
95 r->i_y += margin_v - fmt_dst->i_y_offset;
96 }
97
OSDTextDestroy(subpicture_t * subpic)98 static void OSDTextDestroy(subpicture_t *subpic)
99 {
100 subpicture_updater_sys_t *sys = subpic->updater.p_sys;
101
102 free(sys->text);
103 free(sys);
104 }
105
vout_OSDText(vout_thread_t * vout,int channel,int position,mtime_t duration,const char * text)106 void vout_OSDText(vout_thread_t *vout, int channel,
107 int position, mtime_t duration, const char *text)
108 {
109 assert( (position & ~SUBPICTURE_ALIGN_MASK) == 0);
110 if (!var_InheritBool(vout, "osd") || duration <= 0)
111 return;
112
113 subpicture_updater_sys_t *sys = malloc(sizeof(*sys));
114 if (!sys)
115 return;
116 sys->position = position;
117 sys->text = strdup(text);
118
119 subpicture_updater_t updater = {
120 .pf_validate = OSDTextValidate,
121 .pf_update = OSDTextUpdate,
122 .pf_destroy = OSDTextDestroy,
123 .p_sys = sys,
124 };
125 subpicture_t *subpic = subpicture_New(&updater);
126 if (!subpic) {
127 free(sys->text);
128 free(sys);
129 return;
130 }
131
132 subpic->i_channel = channel;
133 subpic->i_start = mdate();
134 subpic->i_stop = subpic->i_start + duration;
135 subpic->b_ephemer = true;
136 subpic->b_absolute = false;
137 subpic->b_fade = true;
138
139 vout_PutSubpicture(vout, subpic);
140 }
141
vout_OSDMessage(vout_thread_t * vout,int channel,const char * format,...)142 void vout_OSDMessage(vout_thread_t *vout, int channel, const char *format, ...)
143 {
144 va_list args;
145 va_start(args, format);
146
147 char *string;
148 if (vasprintf(&string, format, args) != -1) {
149 vout_OSDText(vout, channel,
150 SUBPICTURE_ALIGN_TOP|SUBPICTURE_ALIGN_RIGHT, 1000000,
151 string);
152 free(string);
153 }
154 va_end(args);
155 }
156
157