Based on a patch by Wolfram Gloger <wmglo@dent.med.uni-muenchen.de>.
http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2012-December/136677.html
The original patch was rebased by Tudor SUCIU <tudor.suciu@gmail.com>.
Lots of additional features and fixes are made by me.
Fixes ticket #2086.
Changes since last version:
- change default page to all pages
Signed-off-by: Marton Balint <cus@passwd.hu>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -242,6 +242,7 @@ External library support: |
242 | 242 |
--enable-libxvid enable Xvid encoding via xvidcore, |
243 | 243 |
native MPEG-4/Xvid encoder exists [no] |
244 | 244 |
--enable-libzmq enable message passing via libzmq [no] |
245 |
+ --enable-libzvbi enable teletext support via libzvbi [no] |
|
245 | 246 |
--enable-openal enable OpenAL 1.1 capture support [no] |
246 | 247 |
--enable-opencl enable OpenCL code |
247 | 248 |
--enable-openssl enable openssl [no] |
... | ... |
@@ -1205,6 +1206,7 @@ EXTERNAL_LIBRARY_LIST=" |
1205 | 1205 |
libxavs |
1206 | 1206 |
libxvid |
1207 | 1207 |
libzmq |
1208 |
+ libzvbi |
|
1208 | 1209 |
openal |
1209 | 1210 |
opencl |
1210 | 1211 |
openssl |
... | ... |
@@ -2044,6 +2046,7 @@ libxavs_encoder_deps="libxavs" |
2044 | 2044 |
libxvid_encoder_deps="libxvid" |
2045 | 2045 |
libutvideo_decoder_deps="libutvideo" |
2046 | 2046 |
libutvideo_encoder_deps="libutvideo" |
2047 |
+libzvbi_teletext_decoder_deps="libzvbi" |
|
2047 | 2048 |
|
2048 | 2049 |
# demuxers / muxers |
2049 | 2050 |
ac3_demuxer_select="ac3_parser" |
... | ... |
@@ -3767,6 +3770,7 @@ die_license_disabled gpl libvidstab |
3767 | 3767 |
die_license_disabled gpl libx264 |
3768 | 3768 |
die_license_disabled gpl libxavs |
3769 | 3769 |
die_license_disabled gpl libxvid |
3770 |
+die_license_disabled gpl libzvbi |
|
3770 | 3771 |
die_license_disabled gpl x11grab |
3771 | 3772 |
|
3772 | 3773 |
die_license_disabled nonfree libaacplus |
... | ... |
@@ -4245,6 +4249,7 @@ enabled libx264 && require libx264 x264.h x264_encoder_encode -lx264 & |
4245 | 4245 |
enabled libxavs && require libxavs xavs.h xavs_encoder_encode -lxavs |
4246 | 4246 |
enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore |
4247 | 4247 |
enabled libzmq && require_pkg_config libzmq zmq.h zmq_ctx_new |
4248 |
+enabled libzvbi && require libzvbi libzvbi.h vbi_decoder_new -lzvbi |
|
4248 | 4249 |
enabled openal && { { for al_libs in "${OPENAL_LIBS}" "-lopenal" "-lOpenAL32"; do |
4249 | 4250 |
check_lib 'AL/al.h' alGetError "${al_libs}" && break; done } || |
4250 | 4251 |
die "ERROR: openal not found"; } && |
... | ... |
@@ -4635,6 +4640,7 @@ echo "threading support ${thread_type-no}" |
4635 | 4635 |
echo "safe bitstream reader ${safe_bitstream_reader-no}" |
4636 | 4636 |
echo "SDL support ${sdl-no}" |
4637 | 4637 |
echo "opencl enabled ${opencl-no}" |
4638 |
+echo "libzvbi enabled ${libzvbi-no}" |
|
4638 | 4639 |
echo "texi2html enabled ${texi2html-no}" |
4639 | 4640 |
echo "perl enabled ${perl-no}" |
4640 | 4641 |
echo "pod2man enabled ${pod2man-no}" |
... | ... |
@@ -158,4 +158,45 @@ ee450d, 101010, eaeaea, 0ce60b, ec14ed, ebff0b, 0d617a, 7b7b7b, d1d1d1, |
158 | 158 |
7b2a0e, 0d950c, 0f007b, cf0dec, cfa80c, 7c127b}. |
159 | 159 |
@end table |
160 | 160 |
|
161 |
+@section libzvbi-teletext |
|
162 |
+ |
|
163 |
+Libzvbi allows libavcodec to decode DVB teletext pages and DVB teletext |
|
164 |
+subtitles. Requires the presence of the libzvbi headers and library during |
|
165 |
+configuration. You need to explicitly configure the build with |
|
166 |
+@code{--enable-libzvbi}. |
|
167 |
+ |
|
168 |
+@subsection Options |
|
169 |
+ |
|
170 |
+@table @option |
|
171 |
+@item txt_page |
|
172 |
+List of teletext page numbers to decode. You may use the special * string to |
|
173 |
+match all pages. Pages that do not match the specified list are dropped. |
|
174 |
+Default value is *. |
|
175 |
+@item txt_chop_top |
|
176 |
+Discards the top teletext line. Default value is 1. |
|
177 |
+@item txt_format |
|
178 |
+Specifies the format of the decoded subtitles. The teletext decoder is capable |
|
179 |
+of decoding the teletext pages to bitmaps or to simple text, you should use |
|
180 |
+"bitmap" for teletext pages, because certain graphics and colors cannot be |
|
181 |
+expressed in simple text. You might use "text" for teletext based subtitles if |
|
182 |
+your application can handle simple text based subtitles. Default value is |
|
183 |
+bitmap. |
|
184 |
+@item txt_left |
|
185 |
+X offset of generated bitmaps, default is 0. |
|
186 |
+@item txt_top |
|
187 |
+Y offset of generated bitmaps, default is 0. |
|
188 |
+@item txt_chop_spaces |
|
189 |
+Chops leading and trailing spaces and removes empty lines from the generated |
|
190 |
+text. This option is useful for teletext based subtitles where empty spaces may |
|
191 |
+be present at the start or at the end of the lines or empty lines may be |
|
192 |
+present between the subtitle lines because of double-sized teletext charactes. |
|
193 |
+Default value is 1. |
|
194 |
+@item txt_duration |
|
195 |
+Sets the display duration of the decoded teletext pages or subtitles in |
|
196 |
+miliseconds. Default value is 30000 which is 30 seconds. |
|
197 |
+@item txt_transparent |
|
198 |
+Force transparent background of the generated teletext bitmaps. Default value |
|
199 |
+is 0 which means an opaque (black) background. |
|
200 |
+@end table |
|
201 |
+ |
|
161 | 202 |
@c man end SUBTILES DECODERS |
... | ... |
@@ -133,6 +133,20 @@ Go to @url{https://github.com/dekkers/libilbc} and follow the instructions for |
133 | 133 |
installing the library. Then pass @code{--enable-libilbc} to configure to |
134 | 134 |
enable it. |
135 | 135 |
|
136 |
+@section libzvbi |
|
137 |
+ |
|
138 |
+libzvbi is a VBI decoding library which can be used by FFmpeg to decode DVB |
|
139 |
+teletext pages and DVB teletext subtitles. |
|
140 |
+ |
|
141 |
+Go to @url{http://sourceforge.net/projects/zapping/} and follow the instructions for |
|
142 |
+installing the library. Then pass @code{--enable-libzvbi} to configure to |
|
143 |
+enable it. |
|
144 |
+ |
|
145 |
+@float NOTE |
|
146 |
+libzvbi is licensed under the GNU General Public License Version 2 or later |
|
147 |
+(see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for details), |
|
148 |
+you must upgrade FFmpeg's license to GPL in order to use it. |
|
149 |
+@end float |
|
136 | 150 |
|
137 | 151 |
|
138 | 152 |
@chapter Supported File Formats, Codecs or Features |
... | ... |
@@ -947,6 +961,7 @@ performance on systems without hardware floating point support). |
947 | 947 |
@item 3GPP Timed Text @tab @tab @tab X @tab X |
948 | 948 |
@item AQTitle @tab @tab X @tab @tab X |
949 | 949 |
@item DVB @tab X @tab X @tab X @tab X |
950 |
+@item DVB teletext @tab @tab X @tab @tab E |
|
950 | 951 |
@item DVD @tab X @tab X @tab X @tab X |
951 | 952 |
@item JACOsub @tab X @tab X @tab @tab X |
952 | 953 |
@item MicroDVD @tab X @tab X @tab @tab X |
... | ... |
@@ -969,6 +984,8 @@ performance on systems without hardware floating point support). |
969 | 969 |
|
970 | 970 |
@code{X} means that the feature is supported. |
971 | 971 |
|
972 |
+@code{E} means that support is provided through an external library. |
|
973 |
+ |
|
972 | 974 |
@section Network Protocols |
973 | 975 |
|
974 | 976 |
@multitable @columnfractions .4 .1 |
... | ... |
@@ -727,6 +727,7 @@ OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o |
727 | 727 |
OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o |
728 | 728 |
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o |
729 | 729 |
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o |
730 |
+OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o |
|
730 | 731 |
|
731 | 732 |
# parsers |
732 | 733 |
OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ |
... | ... |
@@ -505,6 +505,7 @@ void avcodec_register_all(void) |
505 | 505 |
REGISTER_ENCODER(LIBX264RGB, libx264rgb); |
506 | 506 |
REGISTER_ENCODER(LIBXAVS, libxavs); |
507 | 507 |
REGISTER_ENCODER(LIBXVID, libxvid); |
508 |
+ REGISTER_DECODER(LIBZVBI_TELETEXT, libzvbi_teletext); |
|
508 | 509 |
REGISTER_ENCODER(LIBAACPLUS, libaacplus); |
509 | 510 |
|
510 | 511 |
/* text */ |
511 | 512 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,469 @@ |
0 |
+/* |
|
1 |
+ * Teletext decoding for ffmpeg |
|
2 |
+ * Copyright (c) 2005-2010, 2012 Wolfram Gloger |
|
3 |
+ * Copyright (c) 2013 Marton Balint |
|
4 |
+ * |
|
5 |
+ * This library is free software; you can redistribute it and/or |
|
6 |
+ * modify it under the terms of the GNU Lesser General Public |
|
7 |
+ * License as published by the Free Software Foundation; either |
|
8 |
+ * version 2 of the License, or (at your option) any later version. |
|
9 |
+ * |
|
10 |
+ * This library is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 |
+ * Lesser General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU Lesser General Public |
|
16 |
+ * License along with this library; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
18 |
+ */ |
|
19 |
+ |
|
20 |
+#include "avcodec.h" |
|
21 |
+#include "libavutil/opt.h" |
|
22 |
+#include "libavutil/intreadwrite.h" |
|
23 |
+ |
|
24 |
+#include <libzvbi.h> |
|
25 |
+ |
|
26 |
+#define TEXT_MAXSZ (25 * (56 + 1) * 4 + 2) |
|
27 |
+#define VBI_NB_COLORS 40 |
|
28 |
+#define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) |
|
29 |
+#define VBI_R(rgba) (((rgba) >> 0) & 0xFF) |
|
30 |
+#define VBI_G(rgba) (((rgba) >> 8) & 0xFF) |
|
31 |
+#define VBI_B(rgba) (((rgba) >> 16) & 0xFF) |
|
32 |
+#define VBI_A(rgba) (((rgba) >> 24) & 0xFF) |
|
33 |
+ |
|
34 |
+/* main data structure */ |
|
35 |
+typedef struct TeletextContext |
|
36 |
+{ |
|
37 |
+ AVClass *class; |
|
38 |
+ char *pgno; |
|
39 |
+ int x_offset; |
|
40 |
+ int y_offset; |
|
41 |
+ char *format; |
|
42 |
+ int format_id; /* 0 = bitmap, 1 = text */ |
|
43 |
+ int chop_top; |
|
44 |
+ int sub_duration; /* in msec */ |
|
45 |
+ int transparent_bg; |
|
46 |
+ int chop_spaces; |
|
47 |
+ |
|
48 |
+ int lines_processed; |
|
49 |
+ AVSubtitleRect *sub_rect; |
|
50 |
+ |
|
51 |
+ vbi_decoder * vbi; |
|
52 |
+ vbi_dvb_demux * dx; |
|
53 |
+#ifdef DEBUG |
|
54 |
+ vbi_export * ex; |
|
55 |
+#endif |
|
56 |
+ /* Don't even _think_ about making sliced stack-local! */ |
|
57 |
+ vbi_sliced sliced[64]; |
|
58 |
+} TeletextContext; |
|
59 |
+ |
|
60 |
+/************************************************************************/ |
|
61 |
+ |
|
62 |
+static int |
|
63 |
+chop_spaces_utf8(const unsigned char* t, int len) |
|
64 |
+{ |
|
65 |
+ t += len; |
|
66 |
+ while (len > 0) { |
|
67 |
+ if (*--t != ' ' || (len-1 > 0 && *(t-1) & 0x80)) |
|
68 |
+ break; |
|
69 |
+ --len; |
|
70 |
+ } |
|
71 |
+ return len; |
|
72 |
+} |
|
73 |
+ |
|
74 |
+// draw a page as text |
|
75 |
+static int |
|
76 |
+gen_sub_text(TeletextContext *ctx, vbi_page *page, int chop_top) |
|
77 |
+{ |
|
78 |
+ AVSubtitleRect *sub_rect = ctx->sub_rect; |
|
79 |
+ char *text; |
|
80 |
+ const char *in; |
|
81 |
+ char *out; |
|
82 |
+ char *vbi_text = av_malloc(TEXT_MAXSZ); |
|
83 |
+ int sz; |
|
84 |
+ |
|
85 |
+ if (!vbi_text) |
|
86 |
+ return AVERROR(ENOMEM); |
|
87 |
+ |
|
88 |
+ sz = vbi_print_page_region(page, vbi_text, TEXT_MAXSZ-1, "UTF-8", |
|
89 |
+ /*table mode*/ TRUE, FALSE, |
|
90 |
+ 0, chop_top, |
|
91 |
+ page->columns, page->rows-chop_top); |
|
92 |
+ if (sz <= 0) { |
|
93 |
+ av_log(ctx, AV_LOG_ERROR, "vbi_print error\n"); |
|
94 |
+ av_free(vbi_text); |
|
95 |
+ return AVERROR_EXTERNAL; |
|
96 |
+ } |
|
97 |
+ vbi_text[sz] = '\0'; |
|
98 |
+ in = vbi_text; |
|
99 |
+ out = text = av_malloc(TEXT_MAXSZ); |
|
100 |
+ if (!text) { |
|
101 |
+ av_free(vbi_text); |
|
102 |
+ return AVERROR(ENOMEM); |
|
103 |
+ } |
|
104 |
+ if (ctx->chop_spaces) { |
|
105 |
+ for (;;) { |
|
106 |
+ int nl, sz; |
|
107 |
+ |
|
108 |
+ // skip leading spaces and newlines |
|
109 |
+ in += strspn(in, " \n"); |
|
110 |
+ // compute end of row |
|
111 |
+ for (nl = 0; in[nl]; ++nl) |
|
112 |
+ if (in[nl] == '\n' && (nl==0 || !(in[nl-1] & 0x80))) |
|
113 |
+ break; |
|
114 |
+ if (!in[nl]) |
|
115 |
+ break; |
|
116 |
+ // skip trailing spaces |
|
117 |
+ sz = chop_spaces_utf8(in, nl); |
|
118 |
+ memcpy(out, in, sz); |
|
119 |
+ out += sz; |
|
120 |
+ *out++ = '\n'; |
|
121 |
+ in += nl; |
|
122 |
+ } |
|
123 |
+ } else { |
|
124 |
+ strcpy(text, vbi_text); |
|
125 |
+ out += sz; |
|
126 |
+ *out++ = '\n'; |
|
127 |
+ } |
|
128 |
+ av_free(vbi_text); |
|
129 |
+ *out = '\0'; |
|
130 |
+ if (out > text) { |
|
131 |
+ sub_rect->type = SUBTITLE_TEXT; |
|
132 |
+ sub_rect->text = text; |
|
133 |
+ av_log(ctx, AV_LOG_DEBUG, "subtext:%s:txetbus\n", text); |
|
134 |
+ } else { |
|
135 |
+ sub_rect->type = SUBTITLE_NONE; |
|
136 |
+ av_free(text); |
|
137 |
+ } |
|
138 |
+ return 0; |
|
139 |
+} |
|
140 |
+ |
|
141 |
+static void |
|
142 |
+fix_transparency(TeletextContext *ctx, vbi_page *page, int chop_top, uint8_t transparent_color, int resx, int resy) |
|
143 |
+{ |
|
144 |
+ AVSubtitleRect *sub_rect = ctx->sub_rect; |
|
145 |
+ int iy; |
|
146 |
+ |
|
147 |
+ // Hack for transparency, inspired by VLC code... |
|
148 |
+ for (iy = 0; iy < resy; iy++) { |
|
149 |
+ uint8_t *pixel = sub_rect->pict.data[0] + iy * sub_rect->pict.linesize[0]; |
|
150 |
+ vbi_char *vc = page->text + (iy / 10 + chop_top) * page->columns; |
|
151 |
+ vbi_char *vcnext = vc + page->columns; |
|
152 |
+ for (; vc < vcnext; vc++) { |
|
153 |
+ uint8_t *pixelnext = pixel + 12; |
|
154 |
+ switch (vc->opacity) { |
|
155 |
+ case VBI_TRANSPARENT_SPACE: |
|
156 |
+ memset(pixel, transparent_color, 12); |
|
157 |
+ break; |
|
158 |
+ case VBI_OPAQUE: |
|
159 |
+ case VBI_SEMI_TRANSPARENT: |
|
160 |
+ if (!ctx->transparent_bg) |
|
161 |
+ break; |
|
162 |
+ case VBI_TRANSPARENT_FULL: |
|
163 |
+ for(; pixel < pixelnext; pixel++) |
|
164 |
+ if (*pixel == vc->background) |
|
165 |
+ *pixel = transparent_color; |
|
166 |
+ break; |
|
167 |
+ } |
|
168 |
+ pixel = pixelnext; |
|
169 |
+ } |
|
170 |
+ } |
|
171 |
+} |
|
172 |
+ |
|
173 |
+// draw a page as bitmap |
|
174 |
+static int |
|
175 |
+gen_sub_bitmap(TeletextContext *ctx, vbi_page *page, int chop_top) |
|
176 |
+{ |
|
177 |
+ AVSubtitleRect *sub_rect = ctx->sub_rect; |
|
178 |
+ int resx = page->columns * 12; |
|
179 |
+ int resy = (page->rows - chop_top) * 10; |
|
180 |
+ uint8_t ci, cmax = 0; |
|
181 |
+ int ret; |
|
182 |
+ vbi_char *vc = page->text + (chop_top * page->columns); |
|
183 |
+ vbi_char *vcend = page->text + (page->rows * page->columns); |
|
184 |
+ |
|
185 |
+ for (; vc < vcend; vc++) { |
|
186 |
+ if (vc->opacity != VBI_TRANSPARENT_SPACE) { |
|
187 |
+ cmax = VBI_NB_COLORS; |
|
188 |
+ break; |
|
189 |
+ } |
|
190 |
+ } |
|
191 |
+ |
|
192 |
+ if (cmax == 0) { |
|
193 |
+ av_log(ctx, AV_LOG_DEBUG, "dropping empty page %3x\n", page->pgno); |
|
194 |
+ sub_rect->type = SUBTITLE_NONE; |
|
195 |
+ return 0; |
|
196 |
+ } |
|
197 |
+ |
|
198 |
+ if ((ret = avpicture_alloc(&sub_rect->pict, AV_PIX_FMT_PAL8, resx, resy)) < 0) |
|
199 |
+ return ret; |
|
200 |
+ // Yes, we want to allocate the palette on our own because AVSubtitle works this way |
|
201 |
+ sub_rect->pict.data[1] = NULL; |
|
202 |
+ |
|
203 |
+ vbi_draw_vt_page_region(page, VBI_PIXFMT_PAL8, |
|
204 |
+ sub_rect->pict.data[0], sub_rect->pict.linesize[0], |
|
205 |
+ 0, chop_top, page->columns, page->rows - chop_top, |
|
206 |
+ /*reveal*/ 1, /*flash*/ 1); |
|
207 |
+ |
|
208 |
+ fix_transparency(ctx, page, chop_top, cmax, resx, resy); |
|
209 |
+ sub_rect->x = ctx->x_offset; |
|
210 |
+ sub_rect->y = ctx->y_offset; |
|
211 |
+ sub_rect->w = resx; |
|
212 |
+ sub_rect->h = resy; |
|
213 |
+ sub_rect->nb_colors = (int)cmax + 1; |
|
214 |
+ sub_rect->pict.data[1] = av_mallocz(AVPALETTE_SIZE); |
|
215 |
+ if (!sub_rect->pict.data[1]) { |
|
216 |
+ av_freep(&sub_rect->pict.data[0]); |
|
217 |
+ return AVERROR(ENOMEM); |
|
218 |
+ } |
|
219 |
+ for (ci = 0; ci < cmax; ci++) { |
|
220 |
+ int r, g, b, a; |
|
221 |
+ |
|
222 |
+ r = VBI_R(page->color_map[ci]); |
|
223 |
+ g = VBI_G(page->color_map[ci]); |
|
224 |
+ b = VBI_B(page->color_map[ci]); |
|
225 |
+ a = VBI_A(page->color_map[ci]); |
|
226 |
+ ((uint32_t *)sub_rect->pict.data[1])[ci] = RGBA(r, g, b, a); |
|
227 |
+#ifdef DEBUG |
|
228 |
+ av_log(ctx, AV_LOG_DEBUG, "palette %0x\n", |
|
229 |
+ ((uint32_t *)sub_rect->pict.data[1])[ci]); |
|
230 |
+#endif |
|
231 |
+ } |
|
232 |
+ ((uint32_t *)sub_rect->pict.data[1])[cmax] = RGBA(0, 0, 0, 0); |
|
233 |
+ sub_rect->type = SUBTITLE_BITMAP; |
|
234 |
+ return 0; |
|
235 |
+} |
|
236 |
+ |
|
237 |
+static void |
|
238 |
+handler(vbi_event *ev, void *user_data) |
|
239 |
+{ |
|
240 |
+ TeletextContext *ctx = user_data; |
|
241 |
+ vbi_page page; |
|
242 |
+ int res; |
|
243 |
+ char pgno_str[12]; |
|
244 |
+ vbi_subno subno; |
|
245 |
+ vbi_page_type vpt; |
|
246 |
+ int chop_top; |
|
247 |
+ char *lang; |
|
248 |
+ |
|
249 |
+ snprintf(pgno_str, sizeof pgno_str, "%03x", ev->ev.ttx_page.pgno); |
|
250 |
+ av_log(ctx, AV_LOG_DEBUG, "decoded page %s.%02x\n", |
|
251 |
+ pgno_str, ev->ev.ttx_page.subno & 0xFF); |
|
252 |
+ |
|
253 |
+ if (strcmp(ctx->pgno, "*") && !strstr(ctx->pgno, pgno_str)) |
|
254 |
+ return; |
|
255 |
+ |
|
256 |
+ /* Fetch the page. */ |
|
257 |
+ res = vbi_fetch_vt_page(ctx->vbi, &page, |
|
258 |
+ ev->ev.ttx_page.pgno, |
|
259 |
+ ev->ev.ttx_page.subno, |
|
260 |
+ VBI_WST_LEVEL_3p5, 25, TRUE); |
|
261 |
+ |
|
262 |
+ if (!res) |
|
263 |
+ return; |
|
264 |
+ |
|
265 |
+#ifdef DEBUG |
|
266 |
+ fprintf(stderr, "\nSaving res=%d dy0=%d dy1=%d...\n", |
|
267 |
+ res, page.dirty.y0, page.dirty.y1); |
|
268 |
+ fflush(stderr); |
|
269 |
+ |
|
270 |
+ if (!vbi_export_stdio(ctx->ex, stderr, &page)) |
|
271 |
+ fprintf(stderr, "failed: %s\n", vbi_export_errstr(ctx->ex)); |
|
272 |
+#endif |
|
273 |
+ |
|
274 |
+ vpt = vbi_classify_page(ctx->vbi, ev->ev.ttx_page.pgno, &subno, &lang); |
|
275 |
+ chop_top = ctx->chop_top || |
|
276 |
+ ((page.rows > 1) && (vpt == VBI_SUBTITLE_PAGE)); |
|
277 |
+ |
|
278 |
+ av_log(ctx, AV_LOG_DEBUG, "%d x %d page chop:%d\n", |
|
279 |
+ page.columns, page.rows, chop_top); |
|
280 |
+ |
|
281 |
+ if (!ctx->sub_rect) { |
|
282 |
+ ctx->sub_rect = av_mallocz(sizeof(*ctx->sub_rect)); |
|
283 |
+ if (ctx->sub_rect) { |
|
284 |
+ res = (ctx->format_id == 0) ? |
|
285 |
+ gen_sub_bitmap(ctx, &page, chop_top) : |
|
286 |
+ gen_sub_text (ctx, &page, chop_top); |
|
287 |
+ if (res) |
|
288 |
+ av_freep(&ctx->sub_rect); |
|
289 |
+ } |
|
290 |
+ } else { |
|
291 |
+ // FIXME: Multiple teletext pages in a single packet, some kind of buffering should be done instead of dropping the page... |
|
292 |
+ av_log(ctx, AV_LOG_WARNING, "Missed page %s.%02x.\n", pgno_str, ev->ev.ttx_page.subno & 0xFF); |
|
293 |
+ } |
|
294 |
+ |
|
295 |
+ vbi_unref_page(&page); |
|
296 |
+} |
|
297 |
+ |
|
298 |
+static int |
|
299 |
+teletext_decode_frame(AVCodecContext *avctx, |
|
300 |
+ void *data, int *data_size, |
|
301 |
+ AVPacket *pkt) |
|
302 |
+{ |
|
303 |
+ TeletextContext *ctx = avctx->priv_data; |
|
304 |
+ AVSubtitle *sub = data; |
|
305 |
+ const uint8_t *buf = pkt->data; |
|
306 |
+ unsigned int left = pkt->size; |
|
307 |
+ uint8_t pesheader[45] = {0x00, 0x00, 0x01, 0xbd, 0x00, 0x00, 0x85, 0x80, 0x24, 0x21, 0x00, 0x01, 0x00, 0x01}; |
|
308 |
+ int pesheader_size = sizeof(pesheader); |
|
309 |
+ const uint8_t *pesheader_buf = pesheader; |
|
310 |
+ |
|
311 |
+ if (!ctx->vbi) { |
|
312 |
+ if (!(ctx->vbi = vbi_decoder_new())) |
|
313 |
+ return AVERROR(ENOMEM); |
|
314 |
+ if (!vbi_event_handler_add(ctx->vbi, VBI_EVENT_TTX_PAGE, handler, ctx)) { |
|
315 |
+ vbi_decoder_delete(ctx->vbi); |
|
316 |
+ ctx->vbi = NULL; |
|
317 |
+ return AVERROR(ENOMEM); |
|
318 |
+ } |
|
319 |
+ } |
|
320 |
+ if (!ctx->dx && (!(ctx->dx = vbi_dvb_pes_demux_new (/* callback */ NULL, NULL)))) |
|
321 |
+ return AVERROR(ENOMEM); |
|
322 |
+ |
|
323 |
+ // We allow unreasonably big packets, even if the standard only allows a max size of 1472 |
|
324 |
+ if ((pesheader_size + left) < 184 || (pesheader_size + left) > 65504 || (pesheader_size + left) % 184 != 0) |
|
325 |
+ return AVERROR_INVALIDDATA; |
|
326 |
+ |
|
327 |
+ memset(pesheader + 14, 0xff, pesheader_size - 14); |
|
328 |
+ AV_WB16(pesheader + 4, left + pesheader_size - 6); |
|
329 |
+ |
|
330 |
+ /* PTS is deliberately left as 0 in the PES header, otherwise libzvbi uses |
|
331 |
+ * it to detect dropped frames. Unforunatey the guessed packet PTS values |
|
332 |
+ * (see mpegts demuxer) are not accurate enough to pass that test. */ |
|
333 |
+ vbi_dvb_demux_cor(ctx->dx, ctx->sliced, 64, NULL, &pesheader_buf, &pesheader_size); |
|
334 |
+ |
|
335 |
+ while (left > 0) { |
|
336 |
+ int64_t pts = 0; |
|
337 |
+ unsigned int lines = vbi_dvb_demux_cor(ctx->dx, ctx->sliced, 64, &pts, &buf, &left); |
|
338 |
+#ifdef DEBUG |
|
339 |
+ av_log(avctx, AV_LOG_DEBUG, |
|
340 |
+ "ctx=%p buf_size=%d left=%u lines=%u pts=%f pkt_pts=%f\n", |
|
341 |
+ ctx, pkt->size, left, lines, (double)pts/90000.0, (double)pkt->pts/90000.0); |
|
342 |
+#endif |
|
343 |
+ if (lines > 0) { |
|
344 |
+#ifdef DEBUGx |
|
345 |
+ int i; |
|
346 |
+ for(i=0; i<lines; ++i) |
|
347 |
+ av_log(avctx, AV_LOG_DEBUG, |
|
348 |
+ "lines=%d id=%x\n", i, ctx->sliced[i].id); |
|
349 |
+#endif |
|
350 |
+ vbi_decode(ctx->vbi, ctx->sliced, lines, (double)pts/90000.0); |
|
351 |
+ ctx->lines_processed += lines; |
|
352 |
+ } |
|
353 |
+ } |
|
354 |
+ |
|
355 |
+ // is there a subtitle to pass? |
|
356 |
+ if (ctx->sub_rect) { |
|
357 |
+ sub->format = (ctx->sub_rect->type == SUBTITLE_TEXT ? 1: 0); |
|
358 |
+ sub->start_display_time = 0; |
|
359 |
+ sub->end_display_time = ctx->sub_duration; |
|
360 |
+ sub->num_rects = 0; |
|
361 |
+ |
|
362 |
+ if (ctx->sub_rect->type != SUBTITLE_NONE) { |
|
363 |
+ sub->rects = av_malloc(sizeof(*sub->rects) * 1); |
|
364 |
+ if (sub->rects) { |
|
365 |
+ sub->num_rects = 1; |
|
366 |
+ sub->rects[0] = ctx->sub_rect; |
|
367 |
+ } |
|
368 |
+ } else { |
|
369 |
+ av_log(avctx, AV_LOG_DEBUG, "sending empty sub\n"); |
|
370 |
+ sub->rects = NULL; |
|
371 |
+ } |
|
372 |
+ if (!sub->rects) // no rect was passed |
|
373 |
+ av_free(ctx->sub_rect); |
|
374 |
+ ctx->sub_rect = NULL; |
|
375 |
+ |
|
376 |
+ *data_size = 1; |
|
377 |
+ } else |
|
378 |
+ *data_size = 0; |
|
379 |
+ |
|
380 |
+ return pkt->size; |
|
381 |
+} |
|
382 |
+ |
|
383 |
+static int teletext_init_decoder(AVCodecContext *avctx) |
|
384 |
+{ |
|
385 |
+ TeletextContext *ctx = avctx->priv_data; |
|
386 |
+ unsigned int maj, min, rev; |
|
387 |
+ |
|
388 |
+ vbi_version(&maj, &min, &rev); |
|
389 |
+ if (!(maj > 0 || min > 2 || min == 2 && rev >= 26)) { |
|
390 |
+ av_log(avctx, AV_LOG_ERROR, "decoder needs zvbi version >= 0.2.26.\n"); |
|
391 |
+ return AVERROR_EXTERNAL; |
|
392 |
+ } |
|
393 |
+ |
|
394 |
+ ctx->dx = NULL; |
|
395 |
+ ctx->vbi = NULL; |
|
396 |
+ ctx->sub_rect = NULL; |
|
397 |
+ if (!strcmp(ctx->format, "bitmap")) { |
|
398 |
+ ctx->format_id = 0; |
|
399 |
+ } else if (!strcmp(ctx->format, "text")) { |
|
400 |
+ ctx->format_id = 1; |
|
401 |
+ } else { |
|
402 |
+ av_log(avctx, AV_LOG_ERROR, "unkown format %s\n", ctx->format); |
|
403 |
+ return AVERROR_OPTION_NOT_FOUND; |
|
404 |
+ } |
|
405 |
+ |
|
406 |
+#ifdef DEBUG |
|
407 |
+ { |
|
408 |
+ char *t; |
|
409 |
+ ctx->ex = vbi_export_new("text", &t); |
|
410 |
+ } |
|
411 |
+#endif |
|
412 |
+ av_log(avctx, AV_LOG_VERBOSE, "page filter: %s\n", ctx->pgno); |
|
413 |
+ return 0; |
|
414 |
+} |
|
415 |
+ |
|
416 |
+static int teletext_close_decoder(AVCodecContext *avctx) |
|
417 |
+{ |
|
418 |
+ TeletextContext *ctx = avctx->priv_data; |
|
419 |
+ |
|
420 |
+#ifdef DEBUG |
|
421 |
+ av_log(avctx, AV_LOG_DEBUG, "lines_total=%u\n", ctx->lines_processed); |
|
422 |
+#endif |
|
423 |
+ |
|
424 |
+ vbi_dvb_demux_delete(ctx->dx); |
|
425 |
+ vbi_decoder_delete(ctx->vbi); |
|
426 |
+ ctx->dx = NULL; |
|
427 |
+ ctx->vbi = NULL; |
|
428 |
+ return 0; |
|
429 |
+} |
|
430 |
+ |
|
431 |
+static void teletext_flush(AVCodecContext *avctx) |
|
432 |
+{ |
|
433 |
+ teletext_close_decoder(avctx); |
|
434 |
+} |
|
435 |
+ |
|
436 |
+#define OFFSET(x) offsetof(TeletextContext, x) |
|
437 |
+#define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM |
|
438 |
+static const AVOption options[] = { |
|
439 |
+ {"txt_page", "list of teletext page numbers to decode, * is all", OFFSET(pgno), AV_OPT_TYPE_STRING, {.str = "*"}, 0, 0, SD}, |
|
440 |
+ {"txt_chop_top", "discards the top teletext line", OFFSET(chop_top), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, SD}, |
|
441 |
+ {"txt_format", "format of the subtitles (bitmap or text)", OFFSET(format), AV_OPT_TYPE_STRING, {.str = "bitmap"}, 0, 0, SD}, |
|
442 |
+ {"txt_left", "x offset of generated bitmaps", OFFSET(x_offset), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 65535, SD}, |
|
443 |
+ {"txt_top", "y offset of generated bitmaps", OFFSET(y_offset), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 65535, SD}, |
|
444 |
+ {"txt_chop_spaces", "chops leading and trailing spaces from text", OFFSET(chop_spaces), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, SD}, |
|
445 |
+ {"txt_duration", "display duration of teletext pages in msecs", OFFSET(sub_duration), AV_OPT_TYPE_INT, {.i64 = 30000}, 0, 86400000, SD}, |
|
446 |
+ {"txt_transparent", "force transparent background of the teletext", OFFSET(transparent_bg), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, SD}, |
|
447 |
+ { NULL }, |
|
448 |
+}; |
|
449 |
+ |
|
450 |
+static const AVClass teletext_class = { |
|
451 |
+ .class_name = "libzvbi_teletextdec", |
|
452 |
+ .item_name = av_default_item_name, |
|
453 |
+ .option = options, |
|
454 |
+ .version = LIBAVUTIL_VERSION_INT, |
|
455 |
+}; |
|
456 |
+ |
|
457 |
+AVCodec ff_libzvbi_teletext_decoder = { |
|
458 |
+ .name = "libzvbi_teletextdec", |
|
459 |
+ .type = AVMEDIA_TYPE_SUBTITLE, |
|
460 |
+ .id = CODEC_ID_DVB_TELETEXT, |
|
461 |
+ .priv_data_size = sizeof(TeletextContext), |
|
462 |
+ .init = teletext_init_decoder, |
|
463 |
+ .close = teletext_close_decoder, |
|
464 |
+ .decode = teletext_decode_frame, |
|
465 |
+ .flush = teletext_flush, |
|
466 |
+ .long_name = NULL_IF_CONFIG_SMALL("Libzvbi DVB teletext decoder"), |
|
467 |
+ .priv_class= &teletext_class, |
|
468 |
+}; |
... | ... |
@@ -29,7 +29,7 @@ |
29 | 29 |
#include "libavutil/avutil.h" |
30 | 30 |
|
31 | 31 |
#define LIBAVCODEC_VERSION_MAJOR 55 |
32 |
-#define LIBAVCODEC_VERSION_MINOR 30 |
|
32 |
+#define LIBAVCODEC_VERSION_MINOR 31 |
|
33 | 33 |
#define LIBAVCODEC_VERSION_MICRO 100 |
34 | 34 |
|
35 | 35 |
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ |