Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-1.1
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-1.1
Commits
e9d6753e
Commit
e9d6753e
authored
Jul 06, 2007
by
Jean-Paul Saman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Teletext decoder module based on libzvbi. This is the status of thedj's work at 30 April 2007.
parent
4bb8c510
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
185 additions
and
585 deletions
+185
-585
configure.ac
configure.ac
+15
-0
extras/contrib/src/Makefile
extras/contrib/src/Makefile
+3
-3
extras/contrib/src/packages.mak
extras/contrib/src/packages.mak
+2
-2
modules/codec/Modules.am
modules/codec/Modules.am
+1
-0
modules/codec/zvbi.c
modules/codec/zvbi.c
+164
-580
No files found.
configure.ac
View file @
e9d6753e
...
...
@@ -3782,6 +3782,21 @@ if test "${enable_x264}" != "no"; then
fi
fi
dnl
dnl vbi decoder plugin (using libzbvi)
dnl
AC_ARG_ENABLE(zvbi,
[ --enable-zvbi VBI decoding support with libzvbi (default enabled)])
if test "${enable_zvbi}" != "no"; then
PKG_CHECK_MODULES(ZVBI,
zvbi-0.2 >= 0.2.25,
[
VLC_ADD_LDFLAGS([zvbi],[$ZVBI_LIBS])
VLC_ADD_CFLAGS([zvbi],[$ZVBI_CFLAGS])
VLC_ADD_PLUGINS([zvbi]) ],
[AC_MSG_WARN(ZVBI library not found)])
fi
dnl
dnl CMML plugin
dnl
...
...
extras/contrib/src/Makefile
View file @
e9d6753e
...
...
@@ -1115,10 +1115,10 @@ DISTCLEAN_PKG += libdvdnav-$(LIBDVDNAV_VERSION).tar.bz2
# libdvbpsi
# ***************************************************************************
libdvbpsi
3
-$(LIBDVBPSI_VERSION).tar.gz
:
libdvbpsi
4
-$(LIBDVBPSI_VERSION).tar.gz
:
$(WGET)
$(LIBDVBPSI_URL)
libdvbpsi
:
libdvbpsi
3
-$(LIBDVBPSI_VERSION).tar.gz
libdvbpsi
:
libdvbpsi
4
-$(LIBDVBPSI_VERSION).tar.gz
$(EXTRACT_GZ)
.dvbpsi
:
libdvbpsi
...
...
@@ -1603,7 +1603,7 @@ zvbi: zvbi-$(ZVBI_VERSION).tar.bz2
$(EXTRACT_BZ2)
.zvbi
:
zvbi
(
cd
$<
;
./configure
--prefix
=
$(PREFIX)
&&
make
)
(
cd
$<
;
./configure
--prefix
=
$(PREFIX)
CFLAGS
=
"
$(CFLAGS)
-fnested-functions"
&&
make
&&
make
install
)
touch
$@
CLEAN_FILE
+=
.zvbi
...
...
extras/contrib/src/packages.mak
View file @
e9d6753e
...
...
@@ -92,7 +92,7 @@ LIBDVDCSS_URL=$(VIDEOLAN)/libdvdcss/$(LIBDVDCSS_VERSION)/libdvdcss-$(LIBDVDCSS_V
LIBDVDNAV_VERSION
=
20050211
LIBDVDNAV_URL
=
$(VIDEOLAN)
/testing/contrib/libdvdnav-
$(LIBDVDNAV_VERSION)
.tar.bz2
LIBDVBPSI_VERSION
=
0.1.5
LIBDVBPSI_URL
=
$(VIDEOLAN)
/
contrib/libdvbpsi3
-
$(LIBDVBPSI_VERSION)
.tar.gz
LIBDVBPSI_URL
=
$(VIDEOLAN)
/
libdvbpsi/
$(LIBDVBPSI_VERSION)
/libdvbpsi4
-
$(LIBDVBPSI_VERSION)
.tar.gz
LIVEDOTCOM_VERSION
=
latest
LIVEDOTCOM_URL
=
http://live555.com/liveMedia/public/live555-
$(LIVEDOTCOM_VERSION)
.tar.gz
#GOOM_URL=$(VIDEOLAN)/testing/contrib/goom-macosx-altivec-bin.tar.gz
...
...
@@ -185,7 +185,7 @@ PTHREADS_VERSION=2-7-0
PTHREADS_URL
=
ftp://sources.redhat.com/pub/pthreads-win32/pthreads-w32-
$(PTHREADS_VERSION)
-release
.tar.gz
UNICOWS_VERSION
=
1.1.1
UNICOWS_URL
=
$(SF)
/libunicows/libunicows-
$(UNICOWS_VERSION)
-src
.tar.gz
ZVBI_VERSION
=
0.2.2
2
ZVBI_VERSION
=
0.2.2
5
ZVBI_URL
=
$(SF)
/zapping/zvbi-
$(ZVBI_VERSION)
.tar.bz2
TAGLIB_VERSION
=
1.4
TAGLIB_URL
=
http://developer.kde.org/~wheeler/files/src/taglib-
$(TAGLIB_VERSION)
.tar.gz
...
...
modules/codec/Modules.am
View file @
e9d6753e
...
...
@@ -29,3 +29,4 @@ SOURCES_cvdsub = cvdsub.c
SOURCES_fake = fake.c
SOURCES_realaudio = realaudio.c
SOURCES_sdl_image = sdl_image.c
SOURCES_zvbi = zvbi.c
modules/codec/zvbi.c
View file @
e9d6753e
/*****************************************************************************
*
telx.c : Minimalistic Teletext subtitles decoder
*
zvbi.c : VBI and Teletext PES demux and decoder using libzvbi
*****************************************************************************
* Copyright (C) 2007 Vincent Penne
* Some code converted from ProjectX java dvb decoder (c) 2001-2005 by dvb.matt
* $Id$
*
* Authors: Derk-Jan Hartman <djhartman at m2x dot nl> for M2X
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
...
...
@@ -25,20 +25,41 @@
* http://pdc.ro.nu/teletext.html
*
*****************************************************************************/
/* This module implements:
* ETSI EN 301 775: VBI data in PES
* ETSI EN 300 472: EBU Teletext data in PES
* ETSI EN 300 706: Enhanced Teletext (libzvbi)
* ETSI EN 300 231: Video Programme System [VPS] (libzvbi)
* ETSI EN 300 294: 625-line Wide Screen Signaling [WSS] (libzvbi)
* EIA-608 Revision A: Closed Captioning [CC] (libzvbi)
*/
#include <vlc/vlc.h>
#include <assert.h>
#include <stdint.h>
#include <libzvbi.h>
#include "vlc_vout.h"
#include "vlc_bits.h"
#include "vlc_codec.h"
/* #define TELX_DEBUG */
#ifdef TELX_DEBUG
# define dbg( a ) msg_Dbg a
#else
# define dbg( a )
#endif
typedef
enum
{
DATA_UNIT_EBU_TELETEXT_NON_SUBTITLE
=
0x02
,
DATA_UNIT_EBU_TELETEXT_SUBTITLE
=
0x03
,
DATA_UNIT_EBU_TELETEXT_INVERTED
=
0x0C
,
DATA_UNIT_ZVBI_WSS_CPR1204
=
0xB4
,
DATA_UNIT_ZVBI_CLOSED_CAPTION_525
=
0xB5
,
DATA_UNIT_ZVBI_MONOCHROME_SAMPLES_525
=
0xB6
,
DATA_UNIT_VPS
=
0xC3
,
DATA_UNIT_WSS
=
0xC4
,
DATA_UNIT_CLOSED_CAPTION
=
0xC5
,
DATA_UNIT_MONOCHROME_SAMPLES
=
0xC6
,
DATA_UNIT_STUFFING
=
0xFF
,
}
data_unit_id
;
/*****************************************************************************
* Module descriptor.
...
...
@@ -47,37 +68,20 @@ static int Open ( vlc_object_t * );
static
void
Close
(
vlc_object_t
*
);
static
subpicture_t
*
Decode
(
decoder_t
*
,
block_t
**
);
#define OVERRIDE_PAGE_TEXT N_("Override page")
#define OVERRIDE_PAGE_LONGTEXT N_("Override the indicated page, try this if " \
"your subtitles don't appear (-1 = autodetect from TS, " \
"0 = autodetect from teletext, " \
">0 = actual page number, usually 888 or 889).")
#define IGNORE_SUB_FLAG_TEXT N_("Ignore subtitle flag")
#define IGNORE_SUB_FLAG_LONGTEXT N_("Ignore the subtitle flag, try this if " \
"your subtitles don't appear.")
#define FRENCH_WORKAROUND_TEXT N_("Workaround for France")
#define FRENCH_WORKAROUND_LONGTEXT N_("Some French channels do not flag " \
"their subtitling pages correctly due to a historical " \
"interpretation mistake. Try using this wrong interpretation if " \
"your subtitles don't appear.")
#define PAGE_TEXT N_("Teletext page")
#define PAGE_LONGTEXT N_("Open the indicated Teletext page." \
"Default page is index 100")
vlc_module_begin
();
set_description
(
_
(
"
Teletext subtitles
decoder"
)
);
set_shortname
(
"Teletext"
);
set_capability
(
"decoder"
,
5
0
);
set_description
(
_
(
"
VBI and Teletext
decoder"
)
);
set_shortname
(
"
VBI &
Teletext"
);
set_capability
(
"decoder"
,
5
1
);
set_category
(
CAT_INPUT
);
set_subcategory
(
SUBCAT_INPUT_SCODEC
);
set_callbacks
(
Open
,
Close
);
add_integer
(
"telx-override-page"
,
-
1
,
NULL
,
OVERRIDE_PAGE_TEXT
,
OVERRIDE_PAGE_LONGTEXT
,
VLC_TRUE
);
add_bool
(
"telx-ignore-subtitle-flag"
,
0
,
NULL
,
IGNORE_SUB_FLAG_TEXT
,
IGNORE_SUB_FLAG_LONGTEXT
,
VLC_TRUE
);
add_bool
(
"telx-french-workaround"
,
0
,
NULL
,
FRENCH_WORKAROUND_TEXT
,
FRENCH_WORKAROUND_LONGTEXT
,
VLC_TRUE
);
add_integer
(
"vbi-page"
,
100
,
NULL
,
PAGE_TEXT
,
PAGE_LONGTEXT
,
VLC_FALSE
);
vlc_module_end
();
/****************************************************************************
...
...
@@ -86,76 +90,16 @@ vlc_module_end();
struct
decoder_sys_t
{
int
i_align
;
vlc_bool_t
b_is_subtitle
[
9
];
char
ppsz_lines
[
32
][
128
];
char
psz_prev_text
[
512
];
mtime_t
prev_pts
;
int
i_page
[
9
];
vlc_bool_t
b_erase
[
9
];
uint16_t
*
pi_active_national_set
[
9
];
int
i_wanted_page
,
i_wanted_magazine
;
vlc_bool_t
b_ignore_sub_flag
;
};
/****************************************************************************
* Local data
****************************************************************************/
/*
* My doc only mentions 13 national characters, but experiments show there
* are more, in france for example I already found two more (0x9 and 0xb).
*
* Conversion is in this order :
*
* 0x23 0x24 0x40 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x7b 0x7c 0x7d 0x7e
* (these are the standard ones)
* 0x08 0x09 0x0a 0x0b 0x0c 0x0d (apparently a control character) 0x0e 0x0f
*/
static
uint16_t
ppi_national_subsets
[][
20
]
=
{
{
0x00a3
,
0x0024
,
0x0040
,
0x00ab
,
0x00bd
,
0x00bb
,
0x005e
,
0x0023
,
0x002d
,
0x00bc
,
0x00a6
,
0x00be
,
0x00f7
},
/* english ,000 */
{
0x00e9
,
0x00ef
,
0x00e0
,
0x00eb
,
0x00ea
,
0x00f9
,
0x00ee
,
0x0023
,
0x00e8
,
0x00e2
,
0x00f4
,
0x00fb
,
0x00e7
,
0
,
0x00eb
,
0
,
0x00ef
},
/* french ,001 */
{
0x0023
,
0x00a4
,
0x00c9
,
0x00c4
,
0x00d6
,
0x00c5
,
0x00dc
,
0x005f
,
0x00e9
,
0x00e4
,
0x00f6
,
0x00e5
,
0x00fc
},
/* swedish,finnish,hungarian ,010 */
{
0x0023
,
0x016f
,
0x010d
,
0x0165
,
0x017e
,
0x00fd
,
0x00ed
,
0x0159
,
0x00e9
,
0x00e1
,
0x0115
,
0x00fa
,
0x0161
},
/* czech,slovak ,011 */
{
0x0023
,
0x0024
,
0x00a7
,
0x00c4
,
0x00d6
,
0x00dc
,
0x005e
,
0x005f
,
0x00b0
,
0x00e4
,
0x00f6
,
0x00fc
,
0x00df
},
/* german ,100 */
{
0x00e7
,
0x0024
,
0x00a1
,
0x00e1
,
0x00e9
,
0x00ed
,
0x00f3
,
0x00fa
,
0x00bf
,
0x00fc
,
0x00f1
,
0x00e8
,
0x00e0
},
/* portuguese,spanish ,101 */
{
0x00a3
,
0x0024
,
0x00e9
,
0x00b0
,
0x00e7
,
0x00bb
,
0x005e
,
0x0023
,
0x00f9
,
0x00e0
,
0x00f2
,
0x00e8
,
0x00ec
},
/* italian ,110 */
{
0x0023
,
0x00a4
,
0x0162
,
0x00c2
,
0x015e
,
0x0102
,
0x00ce
,
0x0131
,
0x0163
,
0x00e2
,
0x015f
,
0x0103
,
0x00ee
},
/* rumanian ,111 */
/* I have these tables too, but I don't know how they can be triggered */
{
0x0023
,
0x0024
,
0x0160
,
0x0117
,
0x0119
,
0x017d
,
0x010d
,
0x016b
,
0x0161
,
0x0105
,
0x0173
,
0x017e
,
0x012f
},
/* lettish,lithuanian ,1000 */
{
0x0023
,
0x0144
,
0x0105
,
0x005a
,
0x015a
,
0x0141
,
0x0107
,
0x00f3
,
0x0119
,
0x017c
,
0x015b
,
0x0142
,
0x017a
},
/* polish, 1001 */
{
0x0023
,
0x00cb
,
0x010c
,
0x0106
,
0x017d
,
0x0110
,
0x0160
,
0x00eb
,
0x010d
,
0x0107
,
0x017e
,
0x0111
,
0x0161
},
/* serbian,croatian,slovenian, 1010 */
{
0x0023
,
0x00f5
,
0x0160
,
0x00c4
,
0x00d6
,
0x017e
,
0x00dc
,
0x00d5
,
0x0161
,
0x00e4
,
0x00f6
,
0x017e
,
0x00fc
},
/* estonian ,1011 */
{
0x0054
,
0x011f
,
0x0130
,
0x015e
,
0x00d6
,
0x00c7
,
0x00dc
,
0x011e
,
0x0131
,
0x015f
,
0x00f6
,
0x00e7
,
0x00fc
},
/* turkish ,1100 */
};
vbi_decoder
*
p_vbi_dec
;
vbi_dvb_demux
*
p_dvb_demux
;
unsigned
int
i_wanted_page
;
unsigned
int
i_last_page
;
vlc_bool_t
b_update
;
}
static
void
event_handler
(
vbi_event
*
ev
,
void
*
user_data
);
static
int
RequestPage
(
vlc_object_t
*
p_this
,
char
const
*
psz_cmd
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
);
/*****************************************************************************
* Open: probe the decoder and return score
...
...
@@ -170,7 +114,7 @@ static int Open( vlc_object_t *p_this )
vlc_value_t
val
;
int
i
;
if
(
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
't'
,
'e'
,
'l'
,
'x'
))
if
(
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
't'
,
'e'
,
'l'
,
'x'
)
)
{
return
VLC_EGENERIC
;
}
...
...
@@ -182,65 +126,26 @@ static int Open( vlc_object_t *p_this )
msg_Err
(
p_dec
,
"out of memory"
);
return
VLC_ENOMEM
;
}
memset
(
p_sys
,
0
,
sizeof
(
decoder_sys_t
)
);
p_sys
->
i_align
=
0
;
for
(
i
=
0
;
i
<
9
;
i
++
)
p_sys
->
pi_active_national_set
[
i
]
=
ppi_national_subsets
[
1
];
p_sys
->
p_vbi_dec
=
vbi_decoder_new
();
p_sys
->
p_dvb_demux
=
vbi_dvb_pes_demux_new
(
NULL
,
NULL
);
var_Create
(
p_dec
,
"telx-override-page"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_dec
,
"telx-override-page"
,
&
val
);
if
(
val
.
i_int
==
-
1
&&
p_dec
->
fmt_in
.
subs
.
dvb
.
i_id
!=
-
1
)
{
p_sys
->
i_wanted_magazine
=
p_dec
->
fmt_in
.
subs
.
dvb
.
i_id
>>
16
;
if
(
p_sys
->
i_wanted_magazine
==
0
)
p_sys
->
i_wanted_magazine
=
8
;
p_sys
->
i_wanted_page
=
p_dec
->
fmt_in
.
subs
.
dvb
.
i_id
&
0xff
;
var_Create
(
p_dec
,
"telx-french-workaround"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_dec
,
"telx-french-workaround"
,
&
val
);
if
(
p_sys
->
i_wanted_page
<
100
&&
(
val
.
b_bool
||
(
p_sys
->
i_wanted_page
%
16
)
>=
10
))
{
/* See http://www.nada.kth.se/~ragge/vdr/ttxtsubs/TROUBLESHOOTING.txt
* paragraph about French channels - they mix up decimal and
* hexadecimal */
p_sys
->
i_wanted_page
=
(
p_sys
->
i_wanted_page
/
10
)
*
16
+
(
p_sys
->
i_wanted_page
%
10
);
}
}
else
if
(
val
.
i_int
<=
0
)
{
p_sys
->
i_wanted_magazine
=
-
1
;
p_sys
->
i_wanted_page
=
-
1
;
}
else
if
(
(
p_sys
->
p_vbi_dec
==
NULL
)
||
(
p_sys
->
p_dvb_demux
==
NULL
)
)
{
p_sys
->
i_wanted_magazine
=
val
.
i_int
/
100
;
p_sys
->
i_wanted_page
=
(((
val
.
i_int
%
100
)
/
10
)
<<
4
)
|
((
val
.
i_int
%
100
)
%
10
);
msg_Err
(
p_dec
,
"VBI decoder/demux could not be created."
);
return
VLC_ENOMEM
;
}
var_Create
(
p_dec
,
"telx-ignore-subtitle-flag"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_dec
,
"telx-ignore-subtitle-flag"
,
&
val
);
p_sys
->
b_ignore_sub_flag
=
val
.
b_bool
;
msg_Dbg
(
p_dec
,
"starting telx on magazine %d page %x flag %d"
,
p_sys
->
i_wanted_magazine
,
p_sys
->
i_wanted_page
,
p_sys
->
b_ignore_sub_flag
);
vbi_event_handler_register
(
p_sys
->
p_vbi_dec
,
VBI_EVENT_TTX_PAGE
|
VBI_EVENT_CAPTION
|
VBI_EVENT_NETWORK
|
VBI_EVENT_ASPECT
|
VBI_EVENT_PROG_INFO
,
event_handler
,
p_dec
);
/* Create the var on vlc_global. */
p_sys
->
i_wanted_page
=
var_CreateGetInteger
(
p_dec
->
p_libvlc_global
,
"vbi-page"
);
var_AddCallback
(
p_dec
->
p_libvlc_global
,
"vbi-page"
,
RequestPage
,
p_sys
);
return
VLC_SUCCESS
;
/* error: */
/* if (p_sys) { */
/* free(p_sys); */
/* p_sys = NULL; */
/* } */
/* return VLC_EGENERIC; */
}
/*****************************************************************************
...
...
@@ -251,185 +156,12 @@ static void Close( vlc_object_t *p_this )
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
if
(
p_sys
->
p_vbi_dec
)
vbi_decoder_delete
(
p_sys
->
p_vbi_dec
);
if
(
p_sys
->
p_dvb_demux
)
vbi_dvb_demux_delete
(
p_sys
->
p_dvb_demux
);
free
(
p_sys
);
}
/**************************
* change bits endianness *
**************************/
static
uint8_t
bytereverse
(
int
n
)
{
n
=
(((
n
>>
1
)
&
0x55
)
|
((
n
<<
1
)
&
0xaa
));
n
=
(((
n
>>
2
)
&
0x33
)
|
((
n
<<
2
)
&
0xcc
));
n
=
(((
n
>>
4
)
&
0x0f
)
|
((
n
<<
4
)
&
0xf0
));
return
n
;
}
static
int
hamming_8_4
(
int
a
)
{
switch
(
a
)
{
case
0xA8
:
return
0
;
case
0x0B
:
return
1
;
case
0x26
:
return
2
;
case
0x85
:
return
3
;
case
0x92
:
return
4
;
case
0x31
:
return
5
;
case
0x1C
:
return
6
;
case
0xBF
:
return
7
;
case
0x40
:
return
8
;
case
0xE3
:
return
9
;
case
0xCE
:
return
10
;
case
0x6D
:
return
11
;
case
0x7A
:
return
12
;
case
0xD9
:
return
13
;
case
0xF4
:
return
14
;
case
0x57
:
return
15
;
default:
return
-
1
;
// decoding error , not yet corrected
}
}
// utc-2 --> utf-8
// this is not a general function, but it's enough for what we do here
// the result buffer need to be at least 4 bytes long
static
void
to_utf8
(
char
*
res
,
uint16_t
ch
)
{
if
(
ch
>=
0x80
)
{
if
(
ch
>=
0x800
)
{
res
[
0
]
=
(
ch
>>
12
)
|
0xE0
;
res
[
1
]
=
((
ch
>>
6
)
&
0x3F
)
|
0x80
;
res
[
2
]
=
(
ch
&
0x3F
)
|
0x80
;
res
[
3
]
=
0
;
}
else
{
res
[
0
]
=
(
ch
>>
6
)
|
0xC0
;
res
[
1
]
=
(
ch
&
0x3F
)
|
0x80
;
res
[
2
]
=
0
;
}
}
else
{
res
[
0
]
=
ch
;
res
[
1
]
=
0
;
}
}
static
void
decode_string
(
char
*
res
,
int
res_len
,
decoder_sys_t
*
p_sys
,
int
magazine
,
uint8_t
*
packet
,
int
len
)
{
char
utf8
[
7
];
char
*
pt
=
res
;
int
i
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
int
in
=
bytereverse
(
packet
[
i
]
)
&
0x7f
;
uint16_t
out
=
32
;
size_t
l
;
switch
(
in
)
{
/* special national characters */
case
0x23
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
0
];
break
;
case
0x24
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
1
];
break
;
case
0x40
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
2
];
break
;
case
0x5b
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
3
];
break
;
case
0x5c
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
4
];
break
;
case
0x5d
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
5
];
break
;
case
0x5e
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
6
];
break
;
case
0x5f
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
7
];
break
;
case
0x60
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
8
];
break
;
case
0x7b
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
9
];
break
;
case
0x7c
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
10
];
break
;
case
0x7d
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
11
];
break
;
case
0x7e
:
out
=
p_sys
->
pi_active_national_set
[
magazine
][
12
];
break
;
/* some special control characters (empirical) */
case
0x0d
:
/* apparently this starts a sequence that ends with 0xb 0xb */
while
(
i
+
1
<
len
&&
(
bytereverse
(
packet
[
i
+
1
]
)
&
0x7f
)
!=
0x0b
)
i
++
;
i
+=
2
;
break
;
/* goto skip; */
default:
/* non documented national range 0x08 - 0x0f */
if
(
in
>=
0x08
&&
in
<=
0x0f
)
{
out
=
p_sys
->
pi_active_national_set
[
magazine
][
13
+
in
-
8
];
break
;
}
/* normal ascii */
if
(
in
>
32
&&
in
<
0x7f
)
out
=
in
;
}
/* handle undefined national characters */
if
(
out
==
0
)
out
=
32
;
/* convert to utf-8 */
to_utf8
(
utf8
,
out
);
l
=
strlen
(
utf8
);
if
(
pt
+
l
<
res
+
res_len
-
1
)
{
strcpy
(
pt
,
utf8
);
pt
+=
l
;
}
/* skip: ; */
}
/* end: */
*
pt
++
=
0
;
}
#define MAX_SLICES 32
/*****************************************************************************
* Decode:
...
...
@@ -440,255 +172,44 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
block_t
*
p_block
;
subpicture_t
*
p_spu
=
NULL
;
video_format_t
fmt
;
/* int erase = 0; */
int
len
,
offset
;
#if 0
int i_wanted_magazine = i_conf_wanted_page / 100;
int i_wanted_page = 0x10 * ((i_conf_wanted_page % 100) / 10)
| (i_conf_wanted_page % 10);
#endif
vlc_bool_t
b_update
=
VLC_FALSE
;
char
psz_text
[
512
],
*
pt
=
psz_text
;
char
psz_line
[
256
];
int
i
,
total
;
vlc_bool_t
b_cached
=
VLC_FALSE
;
vbi_page
p_page
;
uint8_t
*
p_pos
;
unsigned
int
i_left
;
if
(
pp_block
==
NULL
||
*
pp_block
==
NULL
)
return
NULL
;
p_block
=
*
pp_block
;
*
pp_block
=
NULL
;
dbg
((
p_dec
,
"start of telx packet with header %2x
\n
"
,
*
(
uint8_t
*
)
p_block
->
p_buffer
));
len
=
p_block
->
i_buffer
;
for
(
offset
=
1
;
offset
+
46
<=
len
;
offset
+=
46
)
{
uint8_t
*
packet
=
(
uint8_t
*
)
p_block
->
p_buffer
+
offset
;
// int vbi = ((0x20 & packet[2]) != 0 ? 0 : 313) + (0x1F & packet[2]);
// dbg((p_dec, "vbi %d header %02x %02x %02x\n", vbi, packet[0], packet[1], packet[2]));
if
(
packet
[
0
]
==
0xFF
)
continue
;
/* if (packet[1] != 0x2C) { */
/* printf("wrong header\n"); */
/* //goto error; */
/* continue; */
/* } */
int
mpag
=
(
hamming_8_4
(
packet
[
4
]
)
<<
4
)
|
hamming_8_4
(
packet
[
5
]
);
int
row
,
magazine
;
if
(
mpag
<
0
)
{
/* decode error */
dbg
((
p_dec
,
"mpag hamming error
\n
"
));
continue
;
}
row
=
0xFF
&
bytereverse
(
mpag
);
magazine
=
(
7
&
row
)
==
0
?
8
:
(
7
&
row
);
row
>>=
3
;
if
(
p_sys
->
i_wanted_page
!=
-
1
&&
magazine
!=
p_sys
->
i_wanted_magazine
)
continue
;
if
(
row
==
0
)
{
/* row 0 : flags and header line */
int
flag
=
0
;
int
a
;
for
(
a
=
0
;
a
<
6
;
a
++
)
{
flag
|=
(
0xF
&
(
bytereverse
(
hamming_8_4
(
packet
[
8
+
a
])
)
>>
4
))
<<
(
a
*
4
);
}
/* if (!p_sys->b_ignore_sub_flag && !(1 & flag>>15)) */
/* continue; */
p_sys
->
i_page
[
magazine
]
=
(
0xF0
&
bytereverse
(
hamming_8_4
(
packet
[
7
])
))
|
(
0xF
&
(
bytereverse
(
hamming_8_4
(
packet
[
6
])
)
>>
4
)
);
decode_string
(
psz_line
,
sizeof
(
psz_line
),
p_sys
,
magazine
,
packet
+
14
,
40
-
14
);
dbg
((
p_dec
,
"mag %d flags %x page %x character set %d subtitles %d"
,
magazine
,
flag
,
p_sys
->
i_page
[
magazine
],
7
&
flag
>>
21
,
1
&
flag
>>
15
,
psz_line
));
p_sys
->
pi_active_national_set
[
magazine
]
=
ppi_national_subsets
[
7
&
(
flag
>>
21
)];
p_sys
->
b_is_subtitle
[
magazine
]
=
p_sys
->
b_ignore_sub_flag
||
(
(
1
&
(
flag
>>
15
))
&&
(
1
&
(
flag
>>
16
))
);
dbg
((
p_dec
,
"FLAGS%s%s%s%s%s%s%s mag_ser %d"
,
(
1
&
(
flag
>>
14
))
?
" news"
:
""
,
(
1
&
(
flag
>>
15
))
?
" subtitle"
:
""
,
(
1
&
(
flag
>>
7
))
?
" erase"
:
""
,
(
1
&
(
flag
>>
16
))
?
" suppressed_head"
:
""
,
(
1
&
(
flag
>>
17
))
?
" update"
:
""
,
(
1
&
(
flag
>>
18
))
?
" interrupt"
:
""
,
(
1
&
(
flag
>>
19
))
?
" inhibit"
:
""
,
(
1
&
(
flag
>>
20
))
));
if
(
(
p_sys
->
i_wanted_page
!=
-
1
&&
p_sys
->
i_page
[
magazine
]
!=
p_sys
->
i_wanted_page
)
||
!
p_sys
->
b_is_subtitle
[
magazine
]
)
continue
;
p_sys
->
b_erase
[
magazine
]
=
(
1
&
(
flag
>>
7
));
dbg
((
p_dec
,
"%ld --> %ld
\n
"
,
(
long
int
)
p_block
->
i_pts
,
(
long
int
)(
p_sys
->
prev_pts
+
1500000
)));
/* kludge here :
* we ignore the erase flag if it happens less than 1.5 seconds
* before last caption
* TODO make this time configurable
* UPDATE the kludge seems to be no more necessary
* so it's commented out*/
if
(
/*p_block->i_pts > p_sys->prev_pts + 1500000 && */
p_sys
->
b_erase
[
magazine
]
)
{
int
i
;
dbg
((
p_dec
,
"ERASE !
\n
"
));
p_sys
->
b_erase
[
magazine
]
=
0
;
for
(
i
=
1
;
i
<
32
;
i
++
)
{
if
(
!
p_sys
->
ppsz_lines
[
i
][
0
]
)
continue
;
/* b_update = VLC_TRUE; */
p_sys
->
ppsz_lines
[
i
][
0
]
=
0
;
}
}
/* replace the row if it's different */
if
(
strcmp
(
psz_line
,
p_sys
->
ppsz_lines
[
row
])
)
{
strncpy
(
p_sys
->
ppsz_lines
[
row
],
psz_line
,
sizeof
(
p_sys
->
ppsz_lines
[
row
])
-
1
);
}
b_update
=
VLC_TRUE
;
}
else
if
(
row
<
24
)
{
char
*
t
;
int
i
;
/* row 1-23 : normal lines */
if
(
(
p_sys
->
i_wanted_page
!=
-
1
&&
p_sys
->
i_page
[
magazine
]
!=
p_sys
->
i_wanted_page
)
||
!
p_sys
->
b_is_subtitle
[
magazine
]
||
(
p_sys
->
i_wanted_page
==
-
1
&&
p_sys
->
i_page
[
magazine
]
>
0x99
)
)
continue
;
decode_string
(
psz_line
,
sizeof
(
psz_line
),
p_sys
,
magazine
,
packet
+
6
,
40
);
t
=
psz_line
;
/* remove starting spaces */
while
(
*
t
==
32
)
t
++
;
/* remove trailing spaces */
for
(
i
=
strlen
(
t
)
-
1
;
i
>=
0
&&
t
[
i
]
==
32
;
i
--
);
t
[
i
+
1
]
=
0
;
/* replace the row if it's different */
if
(
strcmp
(
t
,
p_sys
->
ppsz_lines
[
row
]
)
)
{
strncpy
(
p_sys
->
ppsz_lines
[
row
],
t
,
sizeof
(
p_sys
->
ppsz_lines
[
row
])
-
1
);
b_update
=
VLC_TRUE
;
}
if
(
t
[
0
])
p_sys
->
prev_pts
=
p_block
->
i_pts
;
dbg
((
p_dec
,
"%d %d : "
,
magazine
,
row
));
dbg
((
p_dec
,
"%s
\n
"
,
t
));
#ifdef TELX_DEBUG
{
char
dbg
[
256
];
dbg
[
0
]
=
0
;
for
(
i
=
0
;
i
<
40
;
i
++
)
{
int
in
=
bytereverse
(
packet
[
6
+
i
])
&
0x7f
;
sprintf
(
dbg
+
strlen
(
dbg
),
"%02x "
,
in
);
}
dbg
((
p_dec
,
"%s
\n
"
,
dbg
));
dbg
[
0
]
=
0
;
for
(
i
=
0
;
i
<
40
;
i
++
)
{
decode_string
(
psz_line
,
sizeof
(
psz_line
),
p_sys
,
magazine
,
packet
+
6
+
i
,
1
);
sprintf
(
dbg
+
strlen
(
dbg
),
"%s "
,
psz_line
);
}
dbg
((
p_dec
,
"%s
\n
"
,
dbg
));
}
#endif
p_pos
=
p_block
->
p_buffer
;
i_left
=
p_block
->
i_buffer
;
}
else
if
(
row
==
25
)
while
(
i_left
>
0
)
{
/* row 25 : alternate header line */
if
(
(
p_sys
->
i_wanted_page
!=
-
1
&&
p_sys
->
i_page
[
magazine
]
!=
p_sys
->
i_wanted_page
)
||
!
p_sys
->
b_is_subtitle
[
magazine
]
)
continue
;
vbi_sliced
p_sliced
[
MAX_SLICES
];
unsigned
int
i_lines
=
0
;
int64_t
i_pts
;
decode_string
(
psz_line
,
sizeof
(
psz_line
),
p_sys
,
magazine
,
packet
+
6
,
40
);
i_lines
=
vbi_dvb_demux_cor
(
p_sys
->
p_dvb_demux
,
p_sliced
,
MAX_SLICES
,
&
i_pts
,
&
p_pos
,
&
i_left
);
/* replace the row if it's different */
if
(
strcmp
(
psz_line
,
p_sys
->
ppsz_lines
[
0
]
)
)
{
strncpy
(
p_sys
->
ppsz_lines
[
0
],
psz_line
,
sizeof
(
p_sys
->
ppsz_lines
[
0
])
-
1
);
/* b_update = VLC_TRUE; */
}
if
(
i_lines
>
0
)
vbi_decode
(
p_sys
->
p_vbi_dec
,
p_sliced
,
i_lines
,
i_pts
/
90000
.
0
);
}
/* else if (row == 26) { */
/* // row 26 : TV listings */
/* } else */
/* dbg((p_dec, "%d %d : %s\n", magazine, row, decode_string(p_sys, magazine, packet+6, 40))); */
}
if
(
!
b_update
)
goto
error
;
total
=
0
;
for
(
i
=
1
;
i
<
24
;
i
++
)
{
size_t
l
=
strlen
(
p_sys
->
ppsz_lines
[
i
]
);
if
(
l
>
sizeof
(
psz_text
)
-
total
-
1
)
l
=
sizeof
(
psz_text
)
-
total
-
1
;
stop_decode:
/* Try to see if the page we want is in the cache yet */
b_cached
=
vbi_fetch_vt_page
(
p_sys
->
p_vbi_dec
,
&
p_page
,
vbi_dec2bcd
(
p_sys
->
i_wanted_page
),
VBI_ANY_SUBNO
,
VBI_WST_LEVEL_3p5
,
25
,
FALSE
);
if
(
l
>
0
)
{
memcpy
(
pt
,
p_sys
->
ppsz_lines
[
i
],
l
);
total
+=
l
;
pt
+=
l
;
if
(
sizeof
(
psz_text
)
-
total
-
1
>
0
)
{
*
pt
++
=
'\n'
;
total
++
;
}
}
}
*
pt
=
0
;
if
(
!
b_cached
)
goto
error
;
if
(
!
strcmp
(
psz_text
,
p_sys
->
psz_prev_text
)
)
if
(
p_sys
->
i_wanted_page
==
p_sys
->
i_last_page
&&
p_sys
->
b_update
!=
VLC_TRUE
)
goto
error
;
dbg
((
p_dec
,
"UPDATE TELETEXT PICTURE
\n
"
));
assert
(
sizeof
(
p_sys
->
psz_prev_text
)
>=
sizeof
(
psz_text
)
);
strcpy
(
p_sys
->
psz_prev_text
,
psz_text
);
p_sys
->
i_last_page
=
p_sys
->
i_wanted_page
;
p_sys
->
b_update
=
VLC_FALSE
;
msg_Dbg
(
p_dec
,
"we now have page: %d ready for display"
,
p_sys
->
i_wanted_page
);
/* If there is a page or sub to render, then we do that here */
/* Create the subpicture unit */
p_spu
=
p_dec
->
pf_spu_buffer_new
(
p_dec
);
if
(
!
p_spu
)
...
...
@@ -699,10 +220,14 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
/* Create a new subpicture region */
memset
(
&
fmt
,
0
,
sizeof
(
video_format_t
)
);
fmt
.
i_chroma
=
VLC_FOURCC
(
'T'
,
'E'
,
'X'
,
'T'
);
fmt
.
i_aspect
=
0
;
fmt
.
i_width
=
fmt
.
i_height
=
0
;
fmt
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'G'
,
'B'
,
'A'
);
fmt
.
i_aspect
=
VOUT_ASPECT_FACTOR
;
fmt
.
i_sar_num
=
fmt
.
i_sar_den
=
1
;
fmt
.
i_width
=
fmt
.
i_visible_width
=
p_page
.
columns
*
12
;
fmt
.
i_height
=
fmt
.
i_visible_height
=
p_page
.
rows
*
10
;
fmt
.
i_bits_per_pixel
=
32
;
fmt
.
i_x_offset
=
fmt
.
i_y_offset
=
0
;
p_spu
->
p_region
=
p_spu
->
pf_create_region
(
VLC_OBJECT
(
p_dec
),
&
fmt
);
if
(
p_spu
->
p_region
==
NULL
)
{
...
...
@@ -710,23 +235,43 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
goto
error
;
}
p_spu
->
p_region
->
i_x
=
0
;
p_spu
->
p_region
->
i_y
=
0
;
/* Normal text subs, easy markup */
p_spu
->
i_flags
=
SUBPICTURE_ALIGN_BOTTOM
|
p_sys
->
i_align
;
p_spu
->
i_x
=
p_sys
->
i_align
?
20
:
0
;
p_spu
->
i_y
=
10
;
p_spu
->
i_flags
=
SUBPICTURE_ALIGN_TOP
;
p_spu
->
p_region
->
psz_text
=
strdup
(
psz_text
);
p_spu
->
i_start
=
p_block
->
i_pts
;
p_spu
->
i_stop
=
p_block
->
i_pts
+
p_block
->
i_length
;
p_spu
->
b_ephemer
=
(
p_block
->
i_length
==
0
)
;
p_spu
->
i_stop
=
0
;
p_spu
->
b_ephemer
=
VLC_TRUE
;
p_spu
->
b_absolute
=
VLC_FALSE
;
p_spu
->
b_pausable
=
VLC_TRUE
;
dbg
((
p_dec
,
"%ld --> %ld
\n
"
,
(
long
int
)
p_block
->
i_pts
/
100000
,
(
long
int
)
p_block
->
i_length
/
100000
));
p_spu
->
i_original_picture_width
=
p_page
.
columns
*
12
;
p_spu
->
i_original_picture_height
=
p_page
.
rows
*
10
;
vbi_draw_vt_page
(
&
p_page
,
VBI_PIXFMT_RGBA32_LE
,
p_spu
->
p_region
->
picture
.
p
->
p_pixels
,
1
,
1
);
p_spu
->
p_region
->
picture
.
p
->
i_lines
=
p_page
.
rows
*
10
;
p_spu
->
p_region
->
picture
.
p
->
i_pitch
=
p_page
.
columns
*
12
*
4
;
#if 0
unsigned int i_total, i_textsize = 7000;
char p_text[7000];
i_total = vbi_print_page_region( &p_page, p_text, i_textsize, "ISO-8859-1", 0, 0, 0, 0, p_page.columns, p_page.rows );
p_text[i_total] = '\0';
msg_Dbg( p_dec, "page %x-%x\n%s", p_page.pgno, p_page.subno, p_text );
#endif
//if( p_page != NULL)
vbi_unref_page
(
&
p_page
);
block_Release
(
p_block
);
return
p_spu
;
error:
//if( p_page != NULL)
vbi_unref_page
(
&
p_page
);
if
(
p_spu
!=
NULL
)
{
p_dec
->
pf_spu_buffer_del
(
p_dec
,
p_spu
);
...
...
@@ -737,3 +282,42 @@ error:
return
NULL
;
}
static
void
event_handler
(
vbi_event
*
ev
,
void
*
user_data
)
{
decoder_t
*
p_dec
=
(
decoder_t
*
)
user_data
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
if
(
ev
->
type
==
VBI_EVENT_TTX_PAGE
)
{
/* msg_Dbg( p_dec, "Page %03x.%02x ",
ev->ev.ttx_page.pgno,
ev->ev.ttx_page.subno & 0xFF);
*/
if
(
p_sys
->
i_last_page
==
vbi_bcd2dec
(
ev
->
ev
.
ttx_page
.
pgno
)
)
p_sys
->
b_update
=
VLC_TRUE
;
if
(
ev
->
ev
.
ttx_page
.
clock_update
)
msg_Dbg
(
p_dec
,
"clock"
);
if
(
ev
->
ev
.
ttx_page
.
header_update
)
msg_Dbg
(
p_dec
,
"header"
);
}
else
if
(
ev
->
type
==
VBI_EVENT_CAPTION
)
msg_Dbg
(
p_dec
,
"Caption line: %x"
,
ev
->
ev
.
caption
.
pgno
);
else
if
(
ev
->
type
==
VBI_EVENT_NETWORK
)
msg_Dbg
(
p_dec
,
"Network change"
);
else
if
(
ev
->
type
==
VBI_EVENT_ASPECT
)
msg_Dbg
(
p_dec
,
"Aspect update"
);
else
if
(
ev
->
type
==
VBI_EVENT_NETWORK
)
msg_Dbg
(
p_dec
,
"Program info received"
);
}
static
int
RequestPage
(
vlc_object_t
*
p_this
,
char
const
*
psz_cmd
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
)
{
decoder_sys_t
*
p_sys
=
p_data
;
if
(
newval
.
i_int
>
0
&&
newval
.
i_int
<
999
)
p_sys
->
i_wanted_page
=
newval
.
i_int
;
return
VLC_SUCCESS
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment