Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
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
Commits
c523f5a5
Commit
c523f5a5
authored
Jul 06, 2004
by
Gildas Bazin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* modules/codec/dvbsub.c: rewrite of the DVB subtitles decoder.
It can finally decode properly all the samples I have.
parent
859483c8
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
800 additions
and
519 deletions
+800
-519
modules/codec/dvbsub.c
modules/codec/dvbsub.c
+800
-519
No files found.
modules/codec/dvbsub.c
View file @
c523f5a5
...
...
@@ -7,6 +7,7 @@
*
* Authors: Damien LUCAS <damien.lucas@anevia.com>
* Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@videolan.org>
*
* 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
...
...
@@ -31,6 +32,8 @@
#include "vlc_bits.h"
//#define DEBUG_DVBSUB 1
/*****************************************************************************
* Module descriptor.
*****************************************************************************/
...
...
@@ -53,24 +56,26 @@ vlc_module_end();
typedef
struct
dvbsub_rle_s
{
uint16_t
i_num
;
uint8_t
i_color_code
;
int
i_color_code
;
int
i_bpp
;
uint8_t
y
;
uint8_t
cr
;
uint8_t
cb
;
uint8_t
t
;
struct
dvbsub_rle_s
*
p_next
;
struct
dvbsub_rle_s
*
p_next
;
}
dvbsub_rle_t
;
/* A subpicture image is a list of codes
* We need to store the length of each line since nothing specify in
* the standard that all lines shou
dl
have the same length
* the standard that all lines shou
ld
have the same length
* WARNING: We assume here that a spu is less than 576 lines high */
typedef
struct
{
uint16_t
i_rows
;
uint16_t
i_cols
[
576
];
dvbsub_rle_t
*
p_last
;
dvbsub_rle_t
*
p_codes
;
dvbsub_rle_t
*
p_last
;
dvbsub_rle_t
*
p_codes
;
}
dvbsub_image_t
;
...
...
@@ -80,17 +85,37 @@ typedef struct dvbsub_objectdef_s
uint16_t
i_id
;
uint8_t
i_type
;
uint8_t
i_provider
;
uint16_t
i_xoffset
;
uint16_t
i_yoffset
;
uint16_t
i_x
;
uint16_t
i_y
;
uint8_t
i_fg_pc
;
uint8_t
i_bg_pc
;
struct
dvbsub_objectdef_s
*
p_next
;
}
dvbsub_objectdef_t
;
/* An object is constituted of 2 images (for interleaving) */
typedef
struct
dvbsub_object_s
{
uint16_t
i_id
;
uint8_t
i_version_number
;
uint8_t
i_coding_method
;
vlc_bool_t
b_non_modify_color
;
dvbsub_image_t
*
topfield
;
dvbsub_image_t
*
bottomfield
;
struct
dvbsub_object_s
*
p_next
;
}
dvbsub_object_t
;
/* The object definition gives the position of the object in a region */
typedef
struct
dvbsub_regiondef_s
{
uint16_t
i_id
;
uint16_t
i_x
;
uint16_t
i_y
;
}
dvbsub_regiondef_t
;
/* The Region is an aera on the image
* with a list of the object definitions associated
* and a CLUT */
* with a list of the object definitions associated and a CLUT */
typedef
struct
dvbsub_region_s
{
uint8_t
i_id
;
...
...
@@ -106,7 +131,11 @@ typedef struct dvbsub_region_s
uint8_t
i_8bp_code
;
uint8_t
i_4bp_code
;
uint8_t
i_2bp_code
;
dvbsub_objectdef_t
*
p_object
;
int
i_object_defs
;
dvbsub_objectdef_t
*
p_object_defs
;
struct
dvbsub_region_s
*
p_next
;
}
dvbsub_region_t
;
...
...
@@ -117,23 +146,11 @@ typedef struct
uint8_t
i_timeout
;
uint8_t
i_state
;
uint8_t
i_version_number
;
uint8_t
i_regions_number
;
dvbsub_region_t
*
regions
;
}
dvbsub_page_t
;
uint8_t
i_region_defs
;
dvbsub_regiondef_t
*
p_region_defs
;
/* An object is constituted of 2 images (for interleaving) */
typedef
struct
dvbsub_object_s
{
uint16_t
i_id
;
uint8_t
i_version_number
;
uint8_t
i_coding_method
;
vlc_bool_t
b_non_modify_color
;
dvbsub_image_t
*
topfield
;
dvbsub_image_t
*
bottomfield
;
struct
dvbsub_object_s
*
p_next
;
}
dvbsub_object_t
;
}
dvbsub_page_t
;
/* The entry in the palette CLUT */
typedef
struct
...
...
@@ -150,41 +167,26 @@ typedef struct
{
uint8_t
i_id
;
uint8_t
i_version_number
;
dvbsub_color_t
c_2b
[
0xff
];
dvbsub_color_t
c_4b
[
0xff
];
dvbsub_color_t
c_8b
[
0xff
];
dvbsub_color_t
c_2b
[
4
];
dvbsub_color_t
c_4b
[
16
];
dvbsub_color_t
c_8b
[
256
];
}
dvbsub_clut_t
;
typedef
struct
typedef
struct
dvbsub_render_s
{
uint
8_t
i_x
;
uint
16_t
i_x
;
uint16_t
i_y
;
dvbsub_image_t
*
p_rle_top
;
dvbsub_image_t
*
p_rle_bot
;
}
dvbsub_render_t
;
typedef
struct
{
int
i_id
;
dvbsub_image_t
*
p_rle_top
;
dvbsub_image_t
*
p_rle_bot
;
mtime_t
i_pts
;
struct
dvbsub_render_s
*
p_next
;
dvbsub_clut_t
*
p_clut
[
0xff
];
dvbsub_page_t
*
p_page
;
dvbsub_object_t
*
p_objects
;
subpicture_t
*
p_spu
[
16
];
int
i_subpic_channel
;
}
dvbsub_all_t
;
}
dvbsub_render_t
;
struct
subpicture_sys_t
{
mtime_t
i_pts
;
void
*
p_data
;
/* rle datas are stored */
vlc_object_t
*
p_input
;
/* Link to the input */
vlc_bool_t
b_obsolete
;
dvbsub_render_t
*
p_objects
;
/* Linked list of objects to render */
};
struct
decoder_sys_t
...
...
@@ -193,7 +195,21 @@ struct decoder_sys_t
bs_t
bs
;
dvbsub_all_t
dvbsub
;
/* Decoder internal data */
int
i_id
;
int
i_ancillary_id
;
mtime_t
i_pts
;
dvbsub_page_t
*
p_page
;
dvbsub_region_t
*
p_regions
;
dvbsub_object_t
*
p_objects
;
dvbsub_clut_t
*
p_clut
[
256
];
dvbsub_clut_t
default_clut
;
subpicture_t
*
p_spu
;
int
i_subpic_channel
;
};
...
...
@@ -219,18 +235,27 @@ struct decoder_sys_t
#define DVBSUB_DT_28_TABLE_DATA 0x21
#define DVBSUB_DT_48_TABLE_DATA 0x22
#define DVBSUB_DT_END_LINE 0xf0
// List of different Page Composition Segment state
// According to EN 300-743, 7.2.1 table 3
#define DVBSUB_PCS_STATE_ACQUISITION 0x01
#define DVBSUB_PCS_STATE_CHANGE 0x10
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
void
Decode
(
decoder_t
*
,
block_t
**
);
static
void
Decode
(
decoder_t
*
,
block_t
**
);
static
void
decode_segment
(
decoder_t
*
,
bs_t
*
);
static
void
decode_page_composition
(
decoder_t
*
,
bs_t
*
);
static
void
decode_region_composition
(
decoder_t
*
,
bs_t
*
);
static
void
decode_object
(
decoder_t
*
,
bs_t
*
);
static
void
decode_clut
(
decoder_t
*
,
bs_t
*
);
static
vout_thread_t
*
FindVout
(
decoder_t
*
);
static
void
free_objects
(
decoder_t
*
);
static
void
free_all
(
decoder_t
*
);
static
int
init
(
dvbsub_all_t
*
,
int
);
static
void
decode_segment
(
decoder_t
*
,
dvbsub_all_t
*
,
bs_t
*
);
static
void
render
(
dvbsub_all_t
*
,
vout_thread_t
*
);
static
void
dvbsub
(
dvbsub_all_t
*
);
static
void
render
(
decoder_t
*
,
vout_thread_t
*
);
static
void
default_clut_init
(
decoder_t
*
);
/*****************************************************************************
* Open: probe the decoder and return score
...
...
@@ -240,8 +265,9 @@ static void dvbsub( dvbsub_all_t * );
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
p_this
)
{
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
decoder_sys_t
*
p_sys
;
int
i
;
if
(
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
'd'
,
'v'
,
'b'
,
's'
)
)
{
...
...
@@ -251,12 +277,20 @@ static int Open( vlc_object_t *p_this )
p_dec
->
pf_decode_sub
=
Decode
;
p_sys
=
p_dec
->
p_sys
=
malloc
(
sizeof
(
decoder_sys_t
)
);
p_sys
->
i_pts
=
0
;
p_sys
->
i_id
=
p_dec
->
fmt_in
.
subs
.
dvb
.
i_id
&
0xFFFF
;
p_sys
->
i_ancillary_id
=
p_dec
->
fmt_in
.
subs
.
dvb
.
i_id
>>
16
;
p_sys
->
p_page
=
NULL
;
p_sys
->
p_regions
=
NULL
;
p_sys
->
p_objects
=
NULL
;
p_sys
->
p_vout
=
NULL
;
init
(
&
p_sys
->
dvbsub
,
p_dec
->
fmt_in
.
subs
.
dvb
.
i_id
)
;
p_sys
->
p_spu
=
NULL
;
for
(
i
=
0
;
i
<
256
;
i
++
)
p_sys
->
p_clut
[
i
]
=
NULL
;
es_format_Init
(
&
p_dec
->
fmt_out
,
SPU_ES
,
VLC_FOURCC
(
'd'
,
'v'
,
'b'
,
's'
)
);
default_clut_init
(
p_dec
);
return
VLC_SUCCESS
;
}
...
...
@@ -270,7 +304,7 @@ static void Close( vlc_object_t *p_this )
if
(
p_sys
->
p_vout
&&
p_sys
->
p_vout
->
p_subpicture
!=
NULL
)
{
subpicture_t
*
p_subpic
;
subpicture_t
*
p_subpic
;
int
i_subpic
;
for
(
i_subpic
=
0
;
i_subpic
<
VOUT_MAX_SUBPICTURES
;
i_subpic
++
)
{
...
...
@@ -284,8 +318,7 @@ static void Close( vlc_object_t *p_this )
}
}
dvbsub
(
&
p_sys
->
dvbsub
);
free_all
(
p_dec
);
free
(
p_sys
);
}
...
...
@@ -305,120 +338,137 @@ static void Decode( decoder_t *p_dec, block_t **pp_block )
p_block
=
*
pp_block
;
*
pp_block
=
NULL
;
p_sys
->
dvbsub
.
i_pts
=
p_block
->
i_pts
;
if
(
p_sys
->
dvbsub
.
i_pts
<=
0
)
p_sys
->
i_pts
=
p_block
->
i_pts
;
if
(
p_sys
->
i_pts
<=
0
)
{
msg_Warn
(
p_dec
,
"non dated subtitle"
);
block_Release
(
p_block
);
return
;
}
p_last_vout
=
p_sys
->
p_vout
;
if
(
(
p_sys
->
p_vout
=
FindVout
(
p_dec
)
)
)
{
int
i_data_identifier
;
int
i_subtitle_stream_id
;
int
i_end_data_marker
;
bs_init
(
&
p_sys
->
bs
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
i_data_identifier
=
bs_read
(
&
p_sys
->
bs
,
8
);
i_subtitle_stream_id
=
bs_read
(
&
p_sys
->
bs
,
8
);
if
(
bs_read
(
&
p_sys
->
bs
,
8
)
!=
0x20
)
/* Data identifier */
{
msg_Dbg
(
p_dec
,
"invalid data identifier"
);
block_Release
(
p_block
);
return
;
}
for
(
;;
)
if
(
bs_read
(
&
p_sys
->
bs
,
8
)
!=
0x20
&&
0
)
/* Subtitle stream id */
{
if
(
bs_show
(
&
p_sys
->
bs
,
8
)
!=
0x0f
)
msg_Dbg
(
p_dec
,
"invalid subtitle stream id"
);
block_Release
(
p_block
);
return
;
}
while
(
bs_show
(
&
p_sys
->
bs
,
8
)
==
0x0f
)
/* Sync byte */
{
break
;
decode_segment
(
p_dec
,
&
p_sys
->
bs
)
;
}
decode_segment
(
p_dec
,
&
p_sys
->
dvbsub
,
&
p_sys
->
bs
);
if
(
bs_read
(
&
p_sys
->
bs
,
8
)
!=
0xff
)
/* End marker */
{
msg_Warn
(
p_dec
,
"end marker not found (corrupted subtitle ?)"
);
block_Release
(
p_block
);
return
;
}
i_end_data_marker
=
bs_read
(
&
p_sys
->
bs
,
8
);
p_last_vout
=
p_sys
->
p_vout
;
if
(
(
p_sys
->
p_vout
=
vlc_object_find
(
p_dec
,
VLC_OBJECT_VOUT
,
FIND_ANYWHERE
)
)
)
{
if
(
p_last_vout
!=
p_sys
->
p_vout
)
{
p_sys
->
dvbsub
.
i_subpic_channel
=
p_sys
->
i_subpic_channel
=
vout_RegisterOSDChannel
(
p_sys
->
p_vout
);
}
/* Check if the page is to be displayed */
if
(
p_sys
->
dvbsub
.
p_page
&&
p_sys
->
dvbsub
.
p_objects
)
{
render
(
&
p_sys
->
dvbsub
,
p_sys
->
p_vout
);
}
if
(
p_sys
->
p_page
)
render
(
p_dec
,
p_sys
->
p_vout
);
vlc_object_release
(
p_sys
->
p_vout
);
}
#ifdef DEBUG_DVBSUB
else
if
(
p_sys
->
p_page
)
render
(
p_dec
,
NULL
);
#endif
block_Release
(
p_block
);
}
/* following functions are local */
/*****************************************************************************
*
FindVout: Find a vout or wait for one to be created.
*
default_clut_init: default clut as defined in EN 300-743 section 10
*****************************************************************************/
static
vo
ut_thread_t
*
FindVou
t
(
decoder_t
*
p_dec
)
static
vo
id
default_clut_ini
t
(
decoder_t
*
p_dec
)
{
for
(
;;
)
{
vout_thread_t
*
p_vout
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
uint8_t
i
;
if
(
p_dec
->
b_die
||
p_dec
->
b_error
)
{
return
NULL
;
}
p_vout
=
vlc_object_find
(
p_dec
,
VLC_OBJECT_VOUT
,
FIND_ANYWHERE
);
if
(
p_vout
)
#define RGB_TO_Y(r, g, b) ((int16_t) 77 * r + 150 * g + 29 * b) / 256;
#define RGB_TO_U(r, g, b) ((int16_t) -44 * r - 87 * g + 131 * b) / 256;
#define RGB_TO_V(r, g, b) ((int16_t) 131 * r - 110 * g - 21 * b) / 256
;
/* 4 entries CLUT */
for
(
i
=
0
;
i
<
4
;
i
++
)
{
return
p_vout
;
}
msleep
(
VOUT_OUTMEM_SLEEP
);
}
}
uint8_t
R
=
0
,
G
=
0
,
B
=
0
,
T
=
0
;
static
int
init
(
dvbsub_all_t
*
p_dvbsub
,
int
i_id
)
{
int
i
;
if
(
!
(
i
&
0x2
)
&&
!
(
i
&
0x1
)
)
T
=
0xFF
;
else
if
(
!
(
i
&
0x2
)
&&
(
i
&
0x1
)
)
R
=
G
=
B
=
0xFF
;
else
if
(
(
i
&
0x2
)
&&
!
(
i
&
0x1
)
)
R
=
G
=
B
=
0
;
else
R
=
G
=
B
=
0x7F
;
memset
(
p_dvbsub
,
0
,
sizeof
(
dvbsub_all_t
)
);
p_sys
->
default_clut
.
c_2b
[
i
].
Y
=
RGB_TO_Y
(
R
,
G
,
B
);
p_sys
->
default_clut
.
c_2b
[
i
].
Cr
=
RGB_TO_U
(
R
,
G
,
B
);
p_sys
->
default_clut
.
c_2b
[
i
].
Cb
=
RGB_TO_V
(
R
,
G
,
B
);
p_sys
->
default_clut
.
c_2b
[
i
].
T
=
T
;
}
p_dvbsub
->
i_pts
=
0
;
p_dvbsub
->
i_id
=
i_id
;
p_dvbsub
->
p_page
=
NULL
;
p_dvbsub
->
p_objects
=
NULL
;
for
(
i
=
0
;
i
<
255
;
i
++
)
/* 16 entries CLUT */
for
(
i
=
0
;
i
<
16
;
i
++
)
{
uint8_t
R
=
0
,
G
=
0
,
B
=
0
,
T
=
0
;
if
(
!
(
i
&
0x8
)
)
{
if
(
!
(
i
&
0x4
)
&&
!
(
i
&
0x2
)
&&
!
(
i
&
0x1
)
)
{
p_dvbsub
->
p_clut
[
i
]
=
NULL
;
T
=
0xFF
;
}
for
(
i
=
0
;
i
<
16
;
i
++
)
else
{
p_dvbsub
->
p_spu
[
i
]
=
NULL
;
R
=
(
i
&
0x1
)
?
0xFF
:
0
;
G
=
(
i
&
0x2
)
?
0xFF
:
0
;
B
=
(
i
&
0x4
)
?
0xFF
:
0
;
}
}
else
{
R
=
(
i
&
0x1
)
?
0x7F
:
0
;
G
=
(
i
&
0x2
)
?
0x7F
:
0
;
B
=
(
i
&
0x4
)
?
0x7F
:
0
;
}
return
0
;
}
static
void
free_all
(
dvbsub_all_t
*
);
p_sys
->
default_clut
.
c_4b
[
i
].
Y
=
RGB_TO_Y
(
R
,
G
,
B
);
p_sys
->
default_clut
.
c_4b
[
i
].
Cr
=
RGB_TO_U
(
R
,
G
,
B
);
p_sys
->
default_clut
.
c_4b
[
i
].
Cb
=
RGB_TO_V
(
R
,
G
,
B
);
p_sys
->
default_clut
.
c_4b
[
i
].
T
=
T
;
}
static
void
dvbsub
(
dvbsub_all_t
*
p_dvbsub
)
{
free_all
(
p_dvbsub
);
/* 256 entries CLUT (TODO) */
memset
(
p_sys
->
default_clut
.
c_8b
,
0xFF
,
256
*
sizeof
(
dvbsub_color_t
)
);
}
static
void
decode_clut
(
dvbsub_all_t
*
p_dvbsub
,
bs_t
*
s
);
static
void
decode_page_composition
(
dvbsub_all_t
*
p_dvbsub
,
bs_t
*
s
);
static
void
decode_region_composition
(
dvbsub_all_t
*
p_dvbsub
,
bs_t
*
s
);
static
void
stop_display
(
dvbsub_all_t
*
p_dvbsub
);
static
void
decode_object
(
dvbsub_all_t
*
p_dvbsub
,
bs_t
*
s
);
static
void
free_page
(
dvbsub_page_t
*
p_p
);
static
void
decode_segment
(
decoder_t
*
p_dec
,
dvbsub_all_t
*
p_dvbspu
,
bs_t
*
s
)
static
void
decode_segment
(
decoder_t
*
p_dec
,
bs_t
*
s
)
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
int
i_type
;
int
i_page_id
;
int
i_size
;
/* sync_byte */
/* sync_byte
(already checked)
*/
bs_skip
(
s
,
8
);
/* segment type */
...
...
@@ -430,45 +480,66 @@ static void decode_segment( decoder_t *p_dec, dvbsub_all_t *p_dvbspu, bs_t *s )
/* segment size */
i_size
=
bs_show
(
s
,
16
);
if
(
i_page_id
!=
p_
dvbspu
->
i
_id
)
if
(
i_page_id
!=
p_
sys
->
i_id
&&
i_page_id
!=
p_sys
->
i_ancillary
_id
)
{
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"subtitle skipped (page id: %i)"
,
i_page_id
);
#endif
bs_skip
(
s
,
8
*
(
2
+
i_size
)
);
return
;
}
#ifdef DEBUG_DVBSUB
if
(
i_page_id
==
p_sys
->
i_id
)
msg_Dbg
(
p_dec
,
"segment (id: %i)"
,
i_page_id
);
else
msg_Dbg
(
p_dec
,
"ancillary segment (id: %i)"
,
i_page_id
);
#endif
switch
(
i_type
)
{
case
DVBSUB_ST_
CLUT_DEFIN
ITION
:
case
DVBSUB_ST_
PAGE_COMPOS
ITION
:
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"
subtitle dvbsub_decode_clut
"
);
msg_Dbg
(
p_dec
,
"
decode_page_composition
"
);
#endif
decode_
clut
(
p_dvbspu
,
s
);
decode_
page_composition
(
p_dec
,
s
);
break
;
case
DVBSUB_ST_PAGE_COMPOSITION
:
case
DVBSUB_ST_REGION_COMPOSITION
:
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"
subtitle dvbsub_decode_page
_composition"
);
msg_Dbg
(
p_dec
,
"
decode_region
_composition"
);
#endif
decode_
page_composition
(
p_dvbspu
,
s
);
decode_
region_composition
(
p_dec
,
s
);
break
;
case
DVBSUB_ST_REGION_COMPOSITION
:
case
DVBSUB_ST_CLUT_DEFINITION
:
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"
subtitle dvbsub_decode_region_composition
"
);
msg_Dbg
(
p_dec
,
"
decode_clut
"
);
#endif
decode_
region_composition
(
p_dvbspu
,
s
);
decode_
clut
(
p_dec
,
s
);
break
;
case
DVBSUB_ST_OBJECT_DATA
:
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"
subtitle dvbsub_
decode_object"
);
msg_Dbg
(
p_dec
,
"decode_object"
);
#endif
decode_object
(
p_d
vbspu
,
s
);
decode_object
(
p_d
ec
,
s
);
break
;
case
DVBSUB_ST_ENDOFDISPLAY
:
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"
subtitle dvbsub_stop_
display"
);
msg_Dbg
(
p_dec
,
"
end of
display"
);
#endif
stop_display
(
p_dvbspu
);
bs_skip
(
s
,
8
*
(
2
+
i_size
)
);
break
;
case
DVBSUB_ST_STUFFING
:
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"skip stuffing"
);
#endif
bs_skip
(
s
,
8
*
(
2
+
i_size
)
);
break
;
default:
msg_Warn
(
p_dec
,
"unsupported segment type: (%04x)"
,
i_type
);
bs_skip
(
s
,
8
*
(
2
+
i_size
)
);
...
...
@@ -476,21 +547,12 @@ static void decode_segment( decoder_t *p_dec, dvbsub_all_t *p_dvbspu, bs_t *s )
}
}
static
void
stop_display
(
dvbsub_all_t
*
p_dvbsub
)
{
int
i
;
for
(
i
=
0
;
p_dvbsub
->
p_spu
[
i
]
!=
NULL
;
i
++
)
{
p_dvbsub
->
p_spu
[
i
]
->
i_stop
=
p_dvbsub
->
i_pts
;
}
}
static
void
decode_clut
(
dvbsub_all_t
*
p_dvbsub
,
bs_t
*
s
)
static
void
decode_clut
(
decoder_t
*
p_dec
,
bs_t
*
s
)
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
uint16_t
i_segment_length
;
uint16_t
i_processed_length
;
dvbsub_clut_t
*
clut
;
dvbsub_clut_t
*
p_
clut
;
uint8_t
i_clut_id
;
uint8_t
i_version_number
;
...
...
@@ -498,29 +560,25 @@ static void decode_clut( dvbsub_all_t *p_dvbsub, bs_t *s )
i_clut_id
=
bs_read
(
s
,
8
);
i_version_number
=
bs_read
(
s
,
4
);
/
/ Check that this id doesn't not already exist
// with the same version number
// And allocate memory if necessary
if
(
p_dvbsub
->
p_clut
[
i_clut_id
]
!=
NULL
)
/
* Check that this id doesn't not already exist with the same version
* number and allocate memory if necessary */
if
(
p_sys
->
p_clut
[
i_clut_id
]
!=
NULL
&&
p_sys
->
p_clut
[
i_clut_id
]
->
i_version_number
==
i_version_number
)
{
if
(
p_dvbsub
->
p_clut
[
i_clut_id
]
->
i_version_number
==
i_version_number
)
{
//TODO skip the right number of bits
/* Nothing to do */
bs_skip
(
s
,
8
*
i_segment_length
-
12
);
return
;
}
else
{
memset
(
p_dvbsub
->
p_clut
[
i_clut_id
],
0
,
sizeof
(
dvbsub_clut_t
)
);
}
}
else
if
(
!
p_sys
->
p_clut
[
i_clut_id
]
)
{
p_
dvbsub
->
p_clut
[
i_clut_id
]
=
malloc
(
sizeof
(
dvbsub_clut_t
)
);
p_
sys
->
p_clut
[
i_clut_id
]
=
malloc
(
sizeof
(
dvbsub_clut_t
)
);
}
clut
=
p_dvbsub
->
p_clut
[
i_clut_id
];
p_clut
=
p_sys
->
p_clut
[
i_clut_id
];
/* We don't have this version of the CLUT: Parse it */
clut
->
i_version_number
=
i_version_number
;
p_
clut
->
i_version_number
=
i_version_number
;
bs_skip
(
s
,
4
);
/* Reserved bits */
i_processed_length
=
2
;
while
(
i_processed_length
<
i_segment_length
)
...
...
@@ -552,119 +610,162 @@ static void decode_clut( dvbsub_all_t *p_dvbsub, bs_t *s )
}
/* According to EN 300-743 section 7.2.3 note 1, type should
* not have more than 1 bit set to one
But, some strams don't
respect this note. */
* not have more than 1 bit set to one
, but some strams don't
*
respect this note. */
if
(
i_type
&
0x04
)
{
clut
->
c_2b
[
i_id
].
Y
=
y
;
clut
->
c_2b
[
i_id
].
Cr
=
cr
;
clut
->
c_2b
[
i_id
].
Cb
=
cb
;
clut
->
c_2b
[
i_id
].
T
=
t
;
p_
clut
->
c_2b
[
i_id
].
Y
=
y
;
p_
clut
->
c_2b
[
i_id
].
Cr
=
cr
;
p_
clut
->
c_2b
[
i_id
].
Cb
=
cb
;
p_
clut
->
c_2b
[
i_id
].
T
=
t
;
}
if
(
i_type
&
0x02
)
{
clut
->
c_4b
[
i_id
].
Y
=
y
;
clut
->
c_4b
[
i_id
].
Cr
=
cr
;
clut
->
c_4b
[
i_id
].
Cb
=
cb
;
clut
->
c_4b
[
i_id
].
T
=
t
;
p_
clut
->
c_4b
[
i_id
].
Y
=
y
;
p_
clut
->
c_4b
[
i_id
].
Cr
=
cr
;
p_
clut
->
c_4b
[
i_id
].
Cb
=
cb
;
p_
clut
->
c_4b
[
i_id
].
T
=
t
;
}
if
(
i_type
&
0x01
)
{
clut
->
c_8b
[
i_id
].
Y
=
y
;
clut
->
c_8b
[
i_id
].
Cr
=
cr
;
clut
->
c_8b
[
i_id
].
Cb
=
cb
;
clut
->
c_8b
[
i_id
].
T
=
t
;
p_
clut
->
c_8b
[
i_id
].
Y
=
y
;
p_
clut
->
c_8b
[
i_id
].
Cr
=
cr
;
p_
clut
->
c_8b
[
i_id
].
Cb
=
cb
;
p_
clut
->
c_8b
[
i_id
].
T
=
t
;
}
}
}
static
void
decode_page_composition
(
d
vbsub_all_t
*
p_dvbsub
,
bs_t
*
s
)
static
void
decode_page_composition
(
d
ecoder_t
*
p_dec
,
bs_t
*
s
)
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
unsigned
int
i_version_number
;
unsigned
int
i_state
;
unsigned
int
i_segment_length
;
uint8_t
i_timeout
;
unsigned
int
i
;
i_segment_length
=
bs_read
(
s
,
16
);
/* A page is composed by one or more region */
/* A page is composed by one or more region: */
i_segment_length
=
bs_read
(
s
,
16
);
i_timeout
=
bs_read
(
s
,
8
);
i_version_number
=
bs_read
(
s
,
4
);
i_state
=
bs_read
(
s
,
2
);
/* TODO We assume it is a new page (i_state) */
if
(
p_dvbsub
->
p_page
)
free_page
(
p_dvbsub
->
p_page
);
bs_skip
(
s
,
2
);
/* Reserved */
/* Allocate a new page */
p_dvbsub
->
p_page
=
malloc
(
sizeof
(
dvbsub_page_t
)
);
p_dvbsub
->
p_page
->
i_timeout
=
i_timeout
;
if
(
i_state
==
DVBSUB_PCS_STATE_CHANGE
)
{
/* End of an epoch, reset decoder buffer */
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"page composition mode change"
);
#endif
free_all
(
p_dec
);
}
else
if
(
!
p_sys
->
p_page
&&
i_state
!=
DVBSUB_PCS_STATE_ACQUISITION
)
{
/* Not a full PCS, we need to wait for one */
return
;
}
/* Number of regions: */
p_dvbsub
->
p_page
->
i_regions_number
=
(
i_segment_length
-
2
)
/
6
;
if
(
i_state
==
DVBSUB_PCS_STATE_ACQUISITION
)
{
/* Make sure we clean up regularly our objects list.
* Is it the best place to do this ? */
free_objects
(
p_dec
);
}
/* Check version number */
if
(
p_sys
->
p_page
&&
p_sys
->
p_page
->
i_version_number
==
i_version_number
)
{
bs_skip
(
s
,
8
*
(
i_segment_length
-
2
)
);
return
;
}
else
if
(
p_sys
->
p_page
)
{
if
(
p_sys
->
p_page
->
i_region_defs
)
free
(
p_sys
->
p_page
->
p_region_defs
);
p_sys
->
p_page
->
i_region_defs
=
0
;
}
/* Special workaround for CAVENA encoders: a page with no regions is sent
* instead of a 0x80 packet (End Of Display) */
if
(
p_dvbsub
->
p_page
->
i_regions_number
==
0
)
if
(
!
p_sys
->
p_page
)
{
stop_display
(
p_dvbsub
);
/* Allocate a new page */
p_sys
->
p_page
=
malloc
(
sizeof
(
dvbsub_page_t
)
);
}
/* End of workaround */
p_dvbsub
->
p_page
->
regions
=
malloc
(
p_dvbsub
->
p_page
->
i_regions_number
*
sizeof
(
dvbsub_region_t
)
);
for
(
i
=
0
;
i
<
p_dvbsub
->
p_page
->
i_regions_number
;
i
++
)
p_sys
->
p_page
->
i_version_number
=
i_version_number
;
p_sys
->
p_page
->
i_timeout
=
i_timeout
;
/* Number of regions */
p_sys
->
p_page
->
i_region_defs
=
(
i_segment_length
-
2
)
/
6
;
if
(
p_sys
->
p_page
->
i_region_defs
==
0
)
return
;
p_sys
->
p_page
->
p_region_defs
=
malloc
(
p_sys
->
p_page
->
i_region_defs
*
sizeof
(
dvbsub_region_t
)
);
for
(
i
=
0
;
i
<
p_sys
->
p_page
->
i_region_defs
;
i
++
)
{
p_
dvbsub
->
p_page
->
region
s
[
i
].
i_id
=
bs_read
(
s
,
8
);
p_
sys
->
p_page
->
p_region_def
s
[
i
].
i_id
=
bs_read
(
s
,
8
);
bs_skip
(
s
,
8
);
/* Reserved */
p_dvbsub
->
p_page
->
regions
[
i
].
i_x
=
bs_read
(
s
,
16
);
p_dvbsub
->
p_page
->
regions
[
i
].
i_y
=
bs_read
(
s
,
16
);
p_dvbsub
->
p_page
->
regions
[
i
].
p_object
=
NULL
;
p_sys
->
p_page
->
p_region_defs
[
i
].
i_x
=
bs_read
(
s
,
16
);
p_sys
->
p_page
->
p_region_defs
[
i
].
i_y
=
bs_read
(
s
,
16
);
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"page_composition, region %i (%i,%i)"
,
i
,
p_sys
->
p_page
->
p_region_defs
[
i
].
i_x
,
p_sys
->
p_page
->
p_region_defs
[
i
].
i_y
);
#endif
}
}
static
void
decode_region_composition
(
dvbsub_all_t
*
p_dvbsub
,
bs_t
*
s
)
static
void
decode_region_composition
(
decoder_t
*
p_dec
,
bs_t
*
s
)
{
dvbsub_region_t
*
p_region
=
NULL
;
unsigned
int
i_segment_length
;
unsigned
int
i_processed_length
;
unsigned
int
i_region_id
;
unsigned
int
i
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
dvbsub_region_t
*
p_region
,
**
pp_region
=
&
p_sys
->
p_regions
;
int
i_segment_length
;
int
i_processed_length
;
int
i_region_id
;
int
i_version_number
;
i_segment_length
=
bs_read
(
s
,
16
);
/* Get region id: */
i_region_id
=
bs_read
(
s
,
8
);
for
(
i
=
0
;
i
<
p_dvbsub
->
p_page
->
i_regions_number
;
i
++
)
{
if
(
p_dvbsub
->
p_page
->
regions
[
i
].
i_id
==
i_region_id
)
i_version_number
=
bs_read
(
s
,
4
);
/* Check if we already have this region */
for
(
p_region
=
p_sys
->
p_regions
;
p_region
!=
NULL
;
p_region
=
p_region
->
p_next
)
{
p_region
=
&
(
p_dvbsub
->
p_page
->
regions
[
i
])
;
}
pp_region
=
&
p_region
->
p_next
;
if
(
p_region
->
i_id
==
i_region_id
)
break
;
}
if
(
p_region
==
NULL
)
/* Check version number */
if
(
p_region
&&
p_region
->
i_version_number
==
i_version_number
)
{
/* TODO
* The region has never been declared before
* Internal error */
fprintf
(
stderr
,
"Decoding of undeclared region N/A
\n
"
);
bs_skip
(
s
,
8
*
(
i_segment_length
-
1
)
-
4
);
return
;
}
else
if
(
p_region
)
{
if
(
p_region
->
i_object_defs
)
free
(
p_region
->
p_object_defs
);
}
/* Skip version number and fill flag */
if
(
bs_show
(
s
,
4
)
==
p_region
->
i_version_number
)
if
(
!
p_region
)
{
fprintf
(
stderr
,
"Skipping already known region N/A
\n
"
);
/* TODO Skip the right number of bits */
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"new region: %i"
,
i_region_id
);
#endif
p_region
=
*
pp_region
=
malloc
(
sizeof
(
dvbsub_region_t
)
);
p_region
->
p_next
=
NULL
;
}
/* Region attributes */
p_region
->
i_version_number
=
bs_read
(
s
,
4
);
p_region
->
i_id
=
i_region_id
;
p_region
->
i_version_number
=
i_version_number
;
p_region
->
b_fill
=
bs_read
(
s
,
1
);
bs_skip
(
s
,
3
);
/* Reserved */
p_region
->
i_width
=
bs_read
(
s
,
16
);
...
...
@@ -677,24 +778,29 @@ static void decode_region_composition( dvbsub_all_t *p_dvbsub, bs_t *s )
p_region
->
i_4bp_code
=
bs_read
(
s
,
4
);
p_region
->
i_2bp_code
=
bs_read
(
s
,
2
);
bs_skip
(
s
,
2
);
/* Reserved */
p_region
->
p_object_defs
=
NULL
;
p_region
->
i_object_defs
=
0
;
/* List of objects in the region: */
/* We already skipped 10 bytes */
/* List of objects in the region */
i_processed_length
=
10
;
while
(
i_processed_length
<
i_segment_length
)
{
dvbsub_objectdef_t
*
p_obj
;
/* We create a new object */
dvbsub_objectdef_t
*
p_obj
=
malloc
(
sizeof
(
dvbsub_objectdef_t
)
);
p_region
->
i_object_defs
++
;
p_region
->
p_object_defs
=
realloc
(
p_region
->
p_object_defs
,
sizeof
(
dvbsub_objectdef_t
)
*
p_region
->
i_object_defs
);
/* We parse object properties */
p_obj
->
p_next
=
NULL
;
p_obj
=
&
p_region
->
p_object_defs
[
p_region
->
i_object_defs
-
1
]
;
p_obj
->
i_id
=
bs_read
(
s
,
16
);
p_obj
->
i_type
=
bs_read
(
s
,
2
);
p_obj
->
i_provider
=
bs_read
(
s
,
2
);
p_obj
->
i_x
offset
=
bs_read
(
s
,
12
);
p_obj
->
i_x
=
bs_read
(
s
,
12
);
bs_skip
(
s
,
4
);
/* Reserved */
p_obj
->
i_y
offset
=
bs_read
(
s
,
12
);
p_obj
->
i_y
=
bs_read
(
s
,
12
);
i_processed_length
+=
6
;
...
...
@@ -705,48 +811,67 @@ static void decode_region_composition( dvbsub_all_t *p_dvbsub, bs_t *s )
p_obj
->
i_bg_pc
=
bs_read
(
s
,
8
);
i_processed_length
+=
2
;
}
}
}
/* we append it */
if
(
p_region
->
p_object
)
{
dvbsub_objectdef_t
*
p_o
;
for
(
p_o
=
p_region
->
p_object
;
;
p_o
=
p_o
->
p_next
)
{
if
(
p_o
->
p_next
==
NULL
)
static
dvbsub_image_t
*
dvbsub_parse_pdata
(
decoder_t
*
,
bs_t
*
,
uint16_t
);
static
uint16_t
dvbsub_pdata2bpp
(
bs_t
*
,
uint16_t
*
,
dvbsub_image_t
*
);
static
uint16_t
dvbsub_pdata4bpp
(
bs_t
*
,
uint16_t
*
,
dvbsub_image_t
*
);
static
uint16_t
dvbsub_pdata8bpp
(
bs_t
*
,
uint16_t
*
,
dvbsub_image_t
*
);
static
void
decode_object
(
decoder_t
*
p_dec
,
bs_t
*
s
)
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
dvbsub_object_t
*
p_obj
,
**
pp_obj
=
&
p_sys
->
p_objects
;
int
i_segment_length
;
int
i_version_number
;
int
i_coding_method
;
int
i_obj_id
;
i_segment_length
=
bs_read
(
s
,
16
);
i_obj_id
=
bs_read
(
s
,
16
);
i_version_number
=
bs_read
(
s
,
4
);
i_coding_method
=
bs_read
(
s
,
2
);
if
(
i_coding_method
)
{
break
;
}
/* TODO: DVB subtitling as characters */
msg_Dbg
(
p_dec
,
"DVB subtitling as characters is not handled!"
);
bs_skip
(
s
,
8
*
(
i_segment_length
-
2
)
-
6
);
return
;
}
p_o
->
p_next
=
p_obj
;
/* Check if we already have this region */
for
(
p_obj
=
p_sys
->
p_objects
;
p_obj
!=
NULL
;
p_obj
=
p_obj
->
p_next
)
{
pp_obj
=
&
p_obj
->
p_next
;
if
(
p_obj
->
i_id
==
i_obj_id
)
break
;
}
else
/* Check version number */
if
(
p_obj
&&
p_obj
->
i_version_number
==
i_version_number
)
{
p_region
->
p_object
=
p_obj
;
bs_skip
(
s
,
8
*
(
i_segment_length
-
2
)
-
6
);
return
;
}
else
if
(
p_obj
)
{
/* Clean structure */
}
}
static
dvbsub_image_t
*
dvbsub_parse_pdata
(
dvbsub_all_t
*
p_dvbsub
,
bs_t
*
s
,
uint16_t
length
);
static
uint16_t
dvbsub_count0x11
(
bs_t
*
s
,
uint16_t
*
p
,
dvbsub_image_t
*
p_image
);
static
void
decode_object
(
dvbsub_all_t
*
p_dvbsub
,
bs_t
*
s
)
{
dvbsub_object_t
*
p_obj
;
uint16_t
i_segment_length
;
/* Memory Allocation */
p_obj
=
malloc
(
sizeof
(
dvbsub_object_t
)
);
if
(
!
p_obj
)
{
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"new object: %i"
,
i_obj_id
);
#endif
p_obj
=
*
pp_obj
=
malloc
(
sizeof
(
dvbsub_object_t
)
);
p_obj
->
p_next
=
NULL
;
}
i_segment_length
=
bs_read
(
s
,
16
);
/* TODO Check we don't already have this object / this version */
p_obj
->
i_id
=
bs_read
(
s
,
16
);
p_obj
->
i_version_number
=
bs_read
(
s
,
4
);
p_obj
->
i_coding_method
=
bs_read
(
s
,
2
);
p_obj
->
b_non_modify_color
=
bs_read
(
s
,
1
);
p_obj
->
i_id
=
i_obj_id
;
p_obj
->
i_version_number
=
i_version_number
;
p_obj
->
i_coding_method
=
i_coding_method
;
p_obj
->
b_non_modify_color
=
bs_read
(
s
,
1
);
bs_skip
(
s
,
1
);
/* Reserved */
if
(
p_obj
->
i_coding_method
==
0x00
)
...
...
@@ -758,22 +883,17 @@ static void decode_object( dvbsub_all_t *p_dvbsub, bs_t *s )
i_bottomfield_length
=
bs_read
(
s
,
16
);
p_obj
->
topfield
=
dvbsub_parse_pdata
(
p_d
vbsub
,
s
,
i_topfield_length
);
dvbsub_parse_pdata
(
p_d
ec
,
s
,
i_topfield_length
);
p_obj
->
bottomfield
=
dvbsub_parse_pdata
(
p_d
vbsub
,
s
,
i_bottomfield_length
);
dvbsub_parse_pdata
(
p_d
ec
,
s
,
i_bottomfield_length
);
}
else
{
bs_skip
(
s
,
(
i_segment_length
-
3
)
*
8
);
/*TODO: DVB subtitling as characters */
/* TODO: DVB subtitling as characters */
}
/* Add this object to the list of the page */
p_obj
->
p_next
=
p_dvbsub
->
p_objects
;
p_dvbsub
->
p_objects
=
p_obj
;
}
static
dvbsub_image_t
*
dvbsub_parse_pdata
(
d
vbsub_all_t
*
p_dvbsub
,
bs_t
*
s
,
static
dvbsub_image_t
*
dvbsub_parse_pdata
(
d
ecoder_t
*
p_dec
,
bs_t
*
s
,
uint16_t
length
)
{
dvbsub_image_t
*
p_image
;
...
...
@@ -789,31 +909,29 @@ static dvbsub_image_t* dvbsub_parse_pdata( dvbsub_all_t *p_dvbsub, bs_t *s,
/* Let's parse it a first time to determine the size of the buffer */
while
(
i_processed_length
<
length
)
{
i_processed_length
++
;
switch
(
bs_read
(
s
,
8
)
)
{
case
0x10
:
fprintf
(
stderr
,
"0x10 N/A
\n
"
);
i_processed_length
+=
dvbsub_pdata2bpp
(
s
,
&
p_image
->
i_cols
[
i_lines
],
p_image
);
break
;
case
0x11
:
i_processed_length
+=
1
+
dvbsub_count0x11
(
s
,
&
(
p_image
->
i_cols
[
i_lines
]),
p_image
);
dvbsub_pdata4bpp
(
s
,
&
p_image
->
i_cols
[
i_lines
],
p_image
);
break
;
case
0x12
:
fprintf
(
stderr
,
"0x12 N/A
\n
"
);
i_processed_length
+=
dvbsub_pdata8bpp
(
s
,
&
p_image
->
i_cols
[
i_lines
],
p_image
);
break
;
case
0x20
:
fprintf
(
stderr
,
"0x20 N/A
\n
"
);
break
;
case
0x21
:
fprintf
(
stderr
,
"0x21 N/A
\n
"
);
break
;
case
0x22
:
fprintf
(
stderr
,
"0x22 N/A
\n
"
);
/* We don't use map tables */
break
;
case
0xf0
:
i_processed_length
++
;
i_lines
++
;
i_lines
++
;
/* End of line code */
break
;
}
}
...
...
@@ -830,9 +948,10 @@ static dvbsub_image_t* dvbsub_parse_pdata( dvbsub_all_t *p_dvbsub, bs_t *s,
return
p_image
;
}
static
void
add_rle_code
(
dvbsub_image_t
*
p
,
uint16_t
num
,
uint8_t
color
)
static
void
add_rle_code
(
dvbsub_image_t
*
p
,
uint16_t
num
,
uint8_t
color
,
int
i_bpp
)
{
if
(
p
->
p_last
!=
NULL
)
if
(
p
->
p_last
!=
NULL
)
{
p
->
p_last
->
p_next
=
malloc
(
sizeof
(
dvbsub_rle_t
)
);
p
->
p_last
=
p
->
p_last
->
p_next
;
...
...
@@ -843,27 +962,99 @@ static void add_rle_code( dvbsub_image_t *p, uint16_t num, uint8_t color )
p
->
p_last
=
p
->
p_codes
;
}
p
->
p_last
->
i_num
=
num
;
p
->
p_last
->
i_color_code
=
color
;
p
->
p_last
->
i_bpp
=
i_bpp
;
p
->
p_last
->
p_next
=
NULL
;
}
static
uint16_t
dvbsub_
count0x11
(
bs_t
*
s
,
uint16_t
*
p
,
static
uint16_t
dvbsub_
pdata2bpp
(
bs_t
*
s
,
uint16_t
*
p
,
dvbsub_image_t
*
p_image
)
{
uint16_t
i_processed
=
0
;
vlc_bool_t
b_stop
=
0
;
uint16_t
i_processed
=
0
;
vlc_bool_t
b_stop
=
0
;
uint16_t
i_count
=
0
;
uint8_t
i_color
=
0
;
uint8_t
i_color
=
0
;
while
(
!
b_stop
)
while
(
!
b_stop
)
{
i_processed
+=
2
;
if
(
(
i_color
=
bs_read
(
s
,
2
))
!=
0x00
)
{
(
*
p
)
++
;
/* Add 1 pixel */
add_rle_code
(
p_image
,
1
,
i_color
,
2
);
}
else
{
i_processed
++
;
if
(
bs_read
(
s
,
1
)
==
0x00
)
// Switch1
{
i_count
=
3
+
bs_read
(
s
,
3
);
(
*
p
)
+=
i_count
;
i_color
=
bs_read
(
s
,
2
);
add_rle_code
(
p_image
,
i_count
,
i_color
,
2
);
i_processed
+=
5
;
}
else
{
i_processed
++
;
if
(
bs_read
(
s
,
1
)
==
0x00
)
//Switch2
{
i_processed
+=
2
;
switch
(
bs_read
(
s
,
2
)
)
//Switch3
{
case
0x00
:
b_stop
=
1
;
break
;
case
0x01
:
add_rle_code
(
p_image
,
2
,
0
,
2
);
break
;
case
0x02
:
i_count
=
12
+
bs_read
(
s
,
4
);
i_color
=
bs_read
(
s
,
2
);
(
*
p
)
+=
i_count
;
i_processed
+=
6
;
add_rle_code
(
p_image
,
i_count
,
i_color
,
2
);
break
;
case
0x03
:
i_count
=
29
+
bs_read
(
s
,
8
);
i_color
=
bs_read
(
s
,
2
);
(
*
p
)
+=
i_count
;
i_processed
+=
10
;
add_rle_code
(
p_image
,
i_count
,
i_color
,
2
);
break
;
default:
break
;
}
}
}
}
}
bs_align
(
s
);
return
(
i_processed
+
7
)
/
8
;
}
static
uint16_t
dvbsub_pdata4bpp
(
bs_t
*
s
,
uint16_t
*
p
,
dvbsub_image_t
*
p_image
)
{
uint16_t
i_processed
=
0
;
vlc_bool_t
b_stop
=
0
;
uint16_t
i_count
=
0
;
uint8_t
i_color
=
0
;
while
(
!
b_stop
)
{
if
(
(
i_color
=
bs_read
(
s
,
4
))
!=
0x00
)
{
(
*
p
)
++
;
i_processed
+=
4
;
/*
1 pixel of color code '0000'
*/
add_rle_code
(
p_image
,
1
,
i_color
);
/*
Add 1 pixel
*/
add_rle_code
(
p_image
,
1
,
i_color
,
4
);
}
else
{
...
...
@@ -873,7 +1064,7 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
{
i_count
=
2
+
bs_read
(
s
,
3
);
(
*
p
)
+=
i_count
;
add_rle_code
(
p_image
,
i_count
,
0x00
);
add_rle_code
(
p_image
,
i_count
,
0x00
,
4
);
}
else
{
...
...
@@ -890,7 +1081,7 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
i_color
=
bs_read
(
s
,
4
);
(
*
p
)
+=
i_count
;
i_processed
+=
12
;
add_rle_code
(
p_image
,
i_count
,
i_color
);
add_rle_code
(
p_image
,
i_count
,
i_color
,
4
);
}
else
{
...
...
@@ -899,26 +1090,26 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
case
0x0
:
(
*
p
)
++
;
i_processed
+=
8
;
add_rle_code
(
p_image
,
1
,
0x00
);
add_rle_code
(
p_image
,
1
,
0x00
,
4
);
break
;
case
0x1
:
(
*
p
)
+=
2
;
i_processed
+=
8
;
add_rle_code
(
p_image
,
2
,
0x00
);
add_rle_code
(
p_image
,
2
,
0x00
,
4
);
break
;
case
0x2
:
i_count
=
9
+
bs_read
(
s
,
4
);
i_color
=
bs_read
(
s
,
4
);
(
*
p
)
+=
i_count
;
i_processed
+=
16
;
add_rle_code
(
p_image
,
i_count
,
i_color
);
add_rle_code
(
p_image
,
i_count
,
i_color
,
4
);
break
;
case
0x3
:
i_count
=
25
+
bs_read
(
s
,
8
);
i_color
=
bs_read
(
s
,
4
);
(
*
p
)
+=
i_count
;
i_processed
+=
20
;
add_rle_code
(
p_image
,
i_count
,
i_color
);
add_rle_code
(
p_image
,
i_count
,
i_color
,
4
);
break
;
}
}
...
...
@@ -931,98 +1122,157 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
return
(
i_processed
+
7
)
/
8
;
}
static
void
free_image
(
dvbsub_image_t
*
p_i
)
static
uint16_t
dvbsub_pdata8bpp
(
bs_t
*
s
,
uint16_t
*
p
,
dvbsub_image_t
*
p_image
)
{
dvbsub_rle_t
*
p1
;
dvbsub_rle_t
*
p2
=
NULL
;
uint16_t
i_processed
=
0
;
vlc_bool_t
b_stop
=
0
;
uint16_t
i_count
=
0
;
uint8_t
i_color
=
0
;
for
(
p1
=
p_i
->
p_codes
;
p1
!=
NULL
;
p1
=
p2
)
while
(
!
b_stop
)
{
i_processed
+=
8
;
if
(
(
i_color
=
bs_read
(
s
,
8
))
!=
0x00
)
{
(
*
p
)
++
;
/* Add 1 pixel */
add_rle_code
(
p_image
,
1
,
i_color
,
8
);
}
else
{
i_processed
++
;
if
(
bs_read
(
s
,
1
)
==
0x00
)
// Switch1
{
if
(
bs_show
(
s
,
7
)
!=
0x00
)
{
i_count
=
bs_read
(
s
,
7
);
(
*
p
)
+=
i_count
;
add_rle_code
(
p_image
,
i_count
,
0x00
,
8
);
}
else
{
p2
=
p1
->
p_next
;
free
(
p1
);
p1
=
NULL
;
bs_skip
(
s
,
7
);
b_stop
=
1
;
}
i_processed
+=
7
;
}
else
{
i_count
=
bs_read
(
s
,
7
);
(
*
p
)
+=
i_count
;
i_color
=
bs_read
(
s
,
8
);
add_rle_code
(
p_image
,
i_count
,
i_color
,
8
);
i_processed
+=
15
;
}
}
}
free
(
p_i
);
}
bs_align
(
s
);
static
void
free_object
(
dvbsub_object_t
*
p_o
)
{
free
(
p_o
);
return
(
i_processed
+
7
)
/
8
;
}
static
void
free_objectdefs
(
dvbsub_objectdef_t
*
p_o
)
static
dvbsub_image_t
*
dup_image
(
dvbsub_image_t
*
p_i
)
{
dvbsub_objectdef_t
*
p1
;
dvbsub_objectdef_t
*
p2
=
NULL
;
dvbsub_image_t
*
p_image
=
malloc
(
sizeof
(
dvbsub_image_t
)
);
dvbsub_rle_t
*
p_rle
=
p_i
->
p_codes
;
*
p_image
=
*
p_i
;
p_image
->
p_last
=
NULL
;
for
(
p1
=
p_o
;
p1
!=
NULL
;
p1
=
p2
)
while
(
p_rle
)
{
p2
=
p1
->
p_next
;
free
(
p1
);
p1
=
NULL
;
dvbsub_rle_t
*
p_last
=
p_image
->
p_last
;
p_image
->
p_last
=
malloc
(
sizeof
(
dvbsub_rle_t
)
);
if
(
!
p_last
)
p_image
->
p_codes
=
p_image
->
p_last
;
if
(
p_last
)
p_last
->
p_next
=
p_image
->
p_last
;
*
p_image
->
p_last
=
*
p_rle
;
p_rle
=
p_rle
->
p_next
;
}
return
p_image
;
}
static
void
free_
regions
(
dvbsub_region_t
*
p_r
,
uint8_t
nb
)
static
void
free_
image
(
dvbsub_image_t
*
p_i
)
{
unsigned
int
i
;
dvbsub_rle_t
*
p1
;
dvbsub_rle_t
*
p2
=
NULL
;
for
(
p1
=
p_i
->
p_codes
;
p1
!=
NULL
;
p1
=
p2
)
{
p2
=
p1
->
p_next
;
free
(
p1
);
p1
=
NULL
;
}
for
(
i
=
0
;
i
<
nb
;
i
++
)
free_objectdefs
(
p_r
[
i
].
p_object
);
free
(
p_r
);
p_r
=
NULL
;
free
(
p_i
);
}
static
void
free_
objects
(
dvbsub_object_t
*
p_o
)
static
void
free_
spu
(
subpicture_t
*
p_spu
)
{
dvbsub_object_t
*
p1
;
dvbsub_object_t
*
p2
=
NULL
;
dvbsub_render_t
*
p_obj
,
*
p_obj_next
;
for
(
p
1
=
p_o
;
p1
!=
NULL
;
p1
=
p2
)
for
(
p
_obj
=
p_spu
->
p_sys
->
p_objects
;
p_obj
!=
NULL
;
p_obj
=
p_obj_next
)
{
p
2
=
p1
->
p_next
;
free_image
(
p1
->
topfield
);
free_image
(
p1
->
bottomfield
);
free
_object
(
p1
);
p
_obj_next
=
p_obj
->
p_next
;
free_image
(
p_obj
->
p_rle_top
);
free_image
(
p_obj
->
p_rle_bot
);
free
(
p_obj
);
}
free
(
p_spu
->
p_sys
);
p_spu
->
p_sys
=
NULL
;
}
static
void
free_
clut
(
dvbsub_clut_t
*
p_
c
)
static
void
free_
objects
(
decoder_t
*
p_de
c
)
{
free
(
p_c
)
;
}
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
dvbsub_object_t
*
p_obj
,
*
p_obj_next
;
static
void
free_page
(
dvbsub_page_t
*
p_p
)
{
free_regions
(
p_p
->
regions
,
p_p
->
i_regions_number
);
free
(
p_p
);
p_p
=
NULL
;
for
(
p_obj
=
p_sys
->
p_objects
;
p_obj
!=
NULL
;
p_obj
=
p_obj_next
)
{
p_obj_next
=
p_obj
->
p_next
;
free_image
(
p_obj
->
topfield
);
free_image
(
p_obj
->
bottomfield
);
free
(
p_obj
);
}
p_sys
->
p_objects
=
NULL
;
}
static
void
free_
spu
(
subpicture_t
*
p_spu
)
static
void
free_
all
(
decoder_t
*
p_dec
)
{
if
(
p_spu
->
p_sys
)
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
dvbsub_region_t
*
p_reg
,
*
p_reg_next
;
int
i
;
for
(
i
=
0
;
i
<
256
;
i
++
)
{
free_image
(((
dvbsub_render_t
*
)
p_spu
->
p_sys
->
p_data
)
->
p_rle_top
);
free_image
(((
dvbsub_render_t
*
)
p_spu
->
p_sys
->
p_data
)
->
p_rle_bot
);
free
(
p_spu
->
p_sys
->
p_data
);
free
(
p_spu
->
p_sys
);
p_spu
->
p_sys
=
NULL
;
if
(
p_sys
->
p_clut
[
i
]
)
free
(
p_sys
->
p_clut
[
i
]
);
p_sys
->
p_clut
[
i
]
=
NULL
;
}
}
static
void
free_all
(
dvbsub_all_t
*
p_a
)
{
unsigned
int
i
;
if
(
p_sys
->
p_page
)
{
if
(
p_sys
->
p_page
->
i_region_defs
)
free
(
p_sys
->
p_page
->
p_region_defs
);
free
(
p_sys
->
p_page
);
p_sys
->
p_page
=
NULL
;
}
for
(
i
=
0
;
i
<
0xff
;
i
++
)
if
(
p_a
->
p_clut
[
i
])
free_clut
(
p_a
->
p_clut
[
i
]
);
for
(
i
=
0
;
i
<
16
;
i
++
)
if
(
p_a
->
p_spu
[
i
])
free_spu
(
p_a
->
p_spu
[
i
]
);
if
(
p_a
->
p_page
)
free_page
(
p_a
->
p_page
);
free_objects
(
p_a
->
p_objects
);
for
(
p_reg
=
p_sys
->
p_regions
;
p_reg
!=
NULL
;
p_reg
=
p_reg_next
)
{
p_reg_next
=
p_reg
->
p_next
;
if
(
p_reg
->
i_object_defs
)
free
(
p_reg
->
p_object_defs
);
free
(
p_reg
);
}
p_sys
->
p_regions
=
NULL
;
free_objects
(
p_dec
);
}
static
void
RenderYUY2
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
,
const
subpicture_t
*
p_spu
)
dvbsub_render_t
*
p_r
)
{
/* Common variables */
uint8_t
*
p_desty
;
...
...
@@ -1030,7 +1280,6 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
uint16_t
i_cnt
;
uint16_t
x
,
y
;
dvbsub_rle_t
*
p_c
;
dvbsub_render_t
*
p_r
=
((
dvbsub_render_t
*
)
p_spu
->
p_sys
->
p_data
);
dvbsub_image_t
*
p_im
=
p_r
->
p_rle_top
;
i
=
0
;
j
=
0
;
...
...
@@ -1088,76 +1337,77 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
}
static
void
RenderI42x
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
,
const
subpicture_t
*
p_spu
)
dvbsub_render_t
*
p_r
)
{
/* Common variables */
uint8_t
*
p_desty
;
uint8_t
*
p_destu
;
uint8_t
*
p_destv
;
uint16_t
i
,
j
;
uint16_t
x
,
y
;
dvbsub_rle_t
*
p_c
;
dvbsub_render_t
*
p_r
=
((
dvbsub_render_t
*
)
p_spu
->
p_sys
->
p_data
);
uint8_t
*
p_desty
=
p_pic
->
Y_PIXELS
;
uint8_t
*
p_destu
=
p_pic
->
U_PIXELS
;
uint8_t
*
p_destv
=
p_pic
->
V_PIXELS
;
dvbsub_image_t
*
p_im
=
p_r
->
p_rle_top
;
i
=
0
;
j
=
0
;
p_desty
=
p_pic
->
Y_PIXELS
;
p_destu
=
p_pic
->
U_PIXELS
;
p_destv
=
p_pic
->
V_PIXELS
;
//let's render the 1st frame
for
(
p_c
=
p_im
->
p_codes
;
p_c
->
p_next
!=
NULL
;
p_c
=
p_c
->
p_next
)
dvbsub_rle_t
*
p_c
;
uint16_t
i
,
j
,
x
,
y
;
int
i_x_subsampling
=
p_vout
->
output
.
i_chroma
==
VLC_FOURCC
(
'I'
,
'4'
,
'2'
,
'2'
)
?
1
:
2
;
/* Let's render the top field */
p_im
=
p_r
->
p_rle_bot
;
i
=
0
;
j
=
0
;
for
(
p_c
=
p_im
->
p_codes
;
p_c
->
p_next
!=
NULL
;
p_c
=
p_c
->
p_next
)
{
if
(
p_c
->
y
!=
0
)
if
(
p_c
->
y
!=
0
&&
p_c
->
t
!=
0xFF
)
{
x
=
j
+
p_r
->
i_x
;
y
=
2
*
i
+
p_r
->
i_y
;
//memset(p_dest+ y*p_pic->U_PITCH*2 + x, p_c->cr, p_c->i_num);
//memset(p_desty+ (y)*p_pic->Y_PITCH + x, p_c->cr, p_c->i_num);
//memset(p_dest+ y*p_pic->V_PITCH*2 + x, p_c->cb, p_c->i_num);
//memset(p_destu+ (y)*p_pic->Y_PITCH + x, p_c->cb, p_c->i_num);
memset
(
p_desty
+
y
*
p_pic
->
Y_PITCH
+
x
,
p_c
->
y
,
p_c
->
i_num
);
//memset(p_desty+ 2*y*p_pic->U_PITCH + x, p_c->cr, p_c->i_num);
//memset(p_desty+ 2*y*p_pic->V_PITCH + x, p_c->cb, p_c->i_num);
x
=
j
+
p_r
->
i_x
;
y
=
2
*
i
+
p_r
->
i_y
;
memset
(
p_desty
+
y
*
p_pic
->
Y_PITCH
+
x
,
p_c
->
y
,
p_c
->
i_num
);
memset
(
p_destu
+
y
/
2
*
p_pic
->
U_PITCH
+
x
/
i_x_subsampling
,
p_c
->
cr
,
p_c
->
i_num
/
i_x_subsampling
);
memset
(
p_destv
+
y
/
2
*
p_pic
->
V_PITCH
+
x
/
i_x_subsampling
,
p_c
->
cb
,
p_c
->
i_num
/
i_x_subsampling
);
}
j
+=
p_c
->
i_num
;
if
(
j
>=
p_im
->
i_cols
[
i
]
)
if
(
j
>=
p_im
->
i_cols
[
i
]
)
{
i
++
;
j
=
0
;
}
if
(
i
>=
p_im
->
i_rows
)
break
;
if
(
i
>=
p_im
->
i_rows
)
break
;
}
//idem for the second frame
p_im
=
p_r
->
p_rle_bot
;
i
=
0
;
j
=
0
;
for
(
p_c
=
p_im
->
p_codes
;
p_c
->
p_next
!=
NULL
;
p_c
=
p_c
->
p_next
)
/* Idem for the bottom field */
p_im
=
p_r
->
p_rle_bot
;
i
=
0
;
j
=
0
;
for
(
p_c
=
p_im
->
p_codes
;
p_c
->
p_next
!=
NULL
;
p_c
=
p_c
->
p_next
)
{
if
(
p_c
->
y
!=
0
&&
p_c
->
t
<
0x20
)
if
(
p_c
->
y
!=
0
&&
p_c
->
t
!=
0xFF
)
{
x
=
j
+
p_r
->
i_x
;
y
=
2
*
i
+
1
+
p_r
->
i_y
;
//memset(p_desty+ y*p_pic->U_PITCH*2 + x, p_c->cr, p_c->i_num);
//memset(p_desty+ y*p_pic->V_PITCH*2 + x, p_c->cb, p_c->i_num);
x
=
j
+
p_r
->
i_x
;
y
=
2
*
i
+
1
+
p_r
->
i_y
;
memset
(
p_desty
+
y
*
p_pic
->
Y_PITCH
+
x
,
p_c
->
y
,
p_c
->
i_num
);
//memset(p_desty+ 2*y*p_pic->U_PITCH + x, p_c->cr, p_c->i_num);
/
/memset(p_desty+ 2*y*p_pic->V_PITCH + x, p_c->cb, p_c->i_num);
/
* No U or V (decimation) */
}
j
+=
p_c
->
i_num
;
if
(
j
>=
p_im
->
i_cols
[
i
]
)
if
(
j
>=
p_im
->
i_cols
[
i
]
)
{
i
++
;
j
=
0
;
}
if
(
i
>=
p_im
->
i_rows
)
break
;
if
(
i
>=
p_im
->
i_rows
)
break
;
}
}
static
void
RenderDVBSUB
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
,
const
subpicture_t
*
p_spu
)
{
/* If we have changed the language on the fly */
dvbsub_render_t
*
p_render
;
if
(
p_spu
->
p_sys
==
NULL
)
return
;
if
(
p_spu
->
p_sys
==
NULL
||
p_spu
->
p_sys
->
b_obsolete
)
p_render
=
p_spu
->
p_sys
->
p_objects
;
while
(
p_render
)
{
return
;
}
switch
(
p_vout
->
output
.
i_chroma
)
{
...
...
@@ -1169,7 +1419,7 @@ static void RenderDVBSUB( vout_thread_t *p_vout, picture_t *p_pic,
/* As long as we just use Y info, I422 and YV12 are just equivalent
* to I420. Remember to change it the day we'll take into account
* U and V info. */
RenderI42x
(
p_vout
,
p_pic
,
p_
spu
);
RenderI42x
(
p_vout
,
p_pic
,
p_
render
);
break
;
/* RV16 target, scaling */
...
...
@@ -1187,123 +1437,154 @@ static void RenderDVBSUB( vout_thread_t *p_vout, picture_t *p_pic,
/* NVidia overlay, no scaling */
case
VLC_FOURCC
(
'Y'
,
'U'
,
'Y'
,
'2'
):
RenderYUY2
(
p_vout
,
p_pic
,
p_
spu
);
RenderYUY2
(
p_vout
,
p_pic
,
p_
render
);
break
;
default:
msg_Err
(
p_vout
,
"unknown chroma, can't render SPU"
);
break
;
}
}
static
void
dvbsub_Destroy
(
subpicture_t
*
p_spu
)
{
free_spu
(
p_spu
);
p_render
=
p_render
->
p_next
;
}
}
static
void
render
(
d
vbsub_all_t
*
dvbsub
,
vout_thread_t
*
p_vout
)
static
void
render
(
d
ecoder_t
*
p_dec
,
vout_thread_t
*
p_vout
)
{
dvbsub_region_t
*
p_region
;
dvbsub_objectdef_t
*
p_objectdef
;
dvbsub_object_t
*
p_o
;
dvbsub_object_t
*
p_object
;
dvbsub_object_t
*
p_object_old
;
dvbsub_render_t
*
p_render
;
dvbsub_rle_t
*
p_c
;
uint8_t
i
,
j
=
0
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
dvbsub_render_t
*
p_render
=
NULL
,
*
p_current
,
*
p_last
=
NULL
;
dvbsub_clut_t
*
p_clut
;
dvbsub_rle_t
*
p_c
;
int
i
,
j
=
0
,
i_timeout
=
0
;
/* Allocate the subpicture internal data. */
#ifdef DEBUG_DVBSUB
if
(
!
p_vout
)
p_sys
->
p_spu
=
malloc
(
sizeof
(
subpicture_t
)
);
else
#endif
p_sys
->
p_spu
=
vout_CreateSubPicture
(
p_vout
,
p_sys
->
i_subpic_channel
,
MEMORY_SUBPICTURE
);
if
(
p_sys
->
p_spu
==
NULL
)
return
;
/* Loop on region definitions */
#ifdef DEBUG_DVBSUB
if
(
p_sys
->
p_page
)
msg_Dbg
(
p_dec
,
"rendering %i regions"
,
p_sys
->
p_page
->
i_region_defs
);
#endif
for
(
i
=
0
;
p_sys
->
p_page
&&
i
<
p_sys
->
p_page
->
i_region_defs
;
i
++
)
{
dvbsub_region_t
*
p_region
;
dvbsub_regiondef_t
*
p_regiondef
;
i_timeout
=
p_sys
->
p_page
->
i_timeout
;
p_regiondef
=
&
p_sys
->
p_page
->
p_region_defs
[
i
];
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"rendering region %i (%i,%i)"
,
i
,
p_regiondef
->
i_x
,
p_regiondef
->
i_y
);
#endif
/* Find associated region */
for
(
p_region
=
p_sys
->
p_regions
;
p_region
!=
NULL
;
p_region
=
p_region
->
p_next
)
{
if
(
p_regiondef
->
i_id
==
p_region
->
i_id
)
break
;
}
/* loop on regions */
for
(
i
=
0
;
i
<
dvbsub
->
p_page
->
i_regions_number
;
i
++
)
if
(
!
p_region
)
{
p_region
=
&
(
dvbsub
->
p_page
->
regions
[
i
]);
msg_Err
(
p_dec
,
"no region founddddd!!!"
);
continue
;
}
/* loop on objects */
for
(
p_objectdef
=
p_region
->
p_object
;
p_objectdef
!=
NULL
;
p_objectdef
=
p_objectdef
->
p_next
)
/* Loop on object definitions */
for
(
j
=
0
;
j
<
p_region
->
i_object_defs
;
j
++
)
{
dvbsub_object_t
*
p_object
;
dvbsub_objectdef_t
*
p_objectdef
;
p_objectdef
=
&
p_region
->
p_object_defs
[
j
];
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"rendering object %i (%i,%i)"
,
p_objectdef
->
i_id
,
p_objectdef
->
i_x
,
p_objectdef
->
i_y
);
#endif
/* Look for the right object */
p_object
=
dvbsub
->
p_objects
;
while
(
!
p_object
&&
p_object
->
i_id
!=
p_objectdef
->
i_id
)
for
(
p_object
=
p_sys
->
p_objects
;
p_object
!=
NULL
;
p_object
=
p_object
->
p_next
)
{
p_object
=
p_object
->
p_next
;
if
(
p_objectdef
->
i_id
==
p_object
->
i_id
)
break
;
}
if
(
!
p_object
)
{
msg_Err
(
p_
vout
,
"internal decoder error"
);
return
;
msg_Err
(
p_
dec
,
"no object founddddd!!!"
);
continue
;
}
/* Allocate the render structure */
p_render
=
malloc
(
sizeof
(
dvbsub_render_t
)
);
p_render
->
i_x
=
p_region
->
i_x
+
p_objectdef
->
i_xoffset
;
p_render
->
i_y
=
p_region
->
i_y
+
p_objectdef
->
i_yoffset
;
p_render
->
p_rle_top
=
p_object
->
topfield
;
p_render
->
p_rle_bot
=
p_object
->
bottomfield
;
p_current
=
malloc
(
sizeof
(
dvbsub_render_t
)
);
p_current
->
p_next
=
NULL
;
p_current
->
i_x
=
p_regiondef
->
i_x
+
p_objectdef
->
i_x
;
p_current
->
i_y
=
p_regiondef
->
i_y
+
p_objectdef
->
i_y
;
p_current
->
p_rle_top
=
dup_image
(
p_object
->
topfield
);
p_current
->
p_rle_bot
=
dup_image
(
p_object
->
bottomfield
);
if
(
!
p_render
)
p_render
=
p_current
;
if
(
p_last
)
p_last
->
p_next
=
p_current
;
p_last
=
p_current
;
// if we did not recieved the CLUT yet
if
(
!
dvbsub
->
p_clut
[
p_region
->
i_clut
]
)
return
;
p_clut
=
p_sys
->
p_clut
[
p_region
->
i_clut
];
if
(
!
p_clut
)
p_clut
=
&
p_sys
->
default_clut
;
/* Compute the color datas according to the appropriate CLUT */
for
(
p_c
=
p_
render
->
p_rle_top
->
p_codes
;
for
(
p_c
=
p_
current
->
p_rle_top
->
p_codes
;
p_c
->
p_next
!=
NULL
;
p_c
=
p_c
->
p_next
)
{
//TODO We assume here we are working in 4bp
p_c
->
y
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
Y
;
p_c
->
cr
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
Cr
;
p_c
->
cb
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
Cb
;
p_c
->
t
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
T
;
dvbsub_color_t
*
p_color
=
(
p_c
->
i_bpp
==
2
)
?
p_clut
->
c_2b
:
(
p_c
->
i_bpp
==
4
)
?
p_clut
->
c_4b
:
p_clut
->
c_8b
;
p_c
->
y
=
p_color
[
p_c
->
i_color_code
].
Y
;
p_c
->
cr
=
p_color
[
p_c
->
i_color_code
].
Cr
;
p_c
->
cb
=
p_color
[
p_c
->
i_color_code
].
Cb
;
p_c
->
t
=
p_color
[
p_c
->
i_color_code
].
T
;
}
for
(
p_c
=
p_
render
->
p_rle_bot
->
p_codes
;
p_c
->
p_next
!=
NULL
;
for
(
p_c
=
p_
current
->
p_rle_bot
->
p_codes
;
p_c
->
p_next
!=
NULL
;
p_c
=
p_c
->
p_next
)
{
//TODO We assume here we are working in 4bp
p_c
->
y
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
Y
;
p_c
->
cr
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
Cr
;
p_c
->
cb
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
Cb
;
p_c
->
t
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
T
;
}
dvbsub_color_t
*
p_color
=
(
p_c
->
i_bpp
==
2
)
?
p_clut
->
c_2b
:
(
p_c
->
i_bpp
==
4
)
?
p_clut
->
c_4b
:
p_clut
->
c_8b
;
/* Allocate the subpicture internal data. */
dvbsub
->
p_spu
[
j
]
=
vout_CreateSubPicture
(
p_vout
,
dvbsub
->
i_subpic_channel
,
MEMORY_SUBPICTURE
);
if
(
dvbsub
->
p_spu
[
j
]
==
NULL
)
{
msg_Err
(
p_vout
,
"Unable to allocate memory, skipping"
);
return
;
p_c
->
y
=
p_color
[
p_c
->
i_color_code
].
Y
;
p_c
->
cr
=
p_color
[
p_c
->
i_color_code
].
Cr
;
p_c
->
cb
=
p_color
[
p_c
->
i_color_code
].
Cb
;
p_c
->
t
=
p_color
[
p_c
->
i_color_code
].
T
;
}
/* Set the pf_render callback */
dvbsub
->
p_spu
[
j
]
->
pf_render
=
RenderDVBSUB
;
dvbsub
->
p_spu
[
j
]
->
p_sys
=
malloc
(
sizeof
(
subpicture_sys_t
)
);
dvbsub
->
p_spu
[
j
]
->
p_sys
->
p_data
=
p_render
;
dvbsub
->
p_spu
[
j
]
->
p_sys
->
b_obsolete
=
0
;
dvbsub
->
p_spu
[
j
]
->
pf_destroy
=
dvbsub_Destroy
;
dvbsub
->
p_spu
[
j
]
->
i_start
=
dvbsub
->
i_pts
;
dvbsub
->
p_spu
[
j
]
->
i_stop
=
dvbsub
->
p_spu
[
j
]
->
i_start
+
dvbsub
->
p_page
->
i_timeout
*
1000000
;
dvbsub
->
p_spu
[
j
]
->
b_ephemer
=
VLC_FALSE
;
// At this stage, we have all we need in p_render
// We need to free the object
//Remove this object from the list
p_object_old
=
p_object
;
if
(
p_object
==
dvbsub
->
p_objects
)
{
dvbsub
->
p_objects
=
p_object
->
p_next
;
}
else
{
for
(
p_o
=
dvbsub
->
p_objects
;
p_o
->
p_next
!=
p_object
;
p_o
=
p_o
->
p_next
);
p_o
->
p_next
=
p_object
->
p_next
;
}
free_object
(
p_object_old
);
vout_DisplaySubPicture
(
p_vout
,
dvbsub
->
p_spu
[
j
]
);
/* Set the pf_render callback */
p_sys
->
p_spu
->
pf_render
=
RenderDVBSUB
;
p_sys
->
p_spu
->
p_sys
=
malloc
(
sizeof
(
subpicture_sys_t
)
);
p_sys
->
p_spu
->
p_sys
->
p_objects
=
p_render
;
p_sys
->
p_spu
->
pf_destroy
=
free_spu
;
p_sys
->
p_spu
->
i_start
=
p_sys
->
i_pts
;
p_sys
->
p_spu
->
i_stop
=
p_sys
->
p_spu
->
i_start
+
i_timeout
*
1000000
;
p_sys
->
p_spu
->
b_ephemer
=
VLC_TRUE
;
j
++
;
}
#ifdef DEBUG_DVBSUB
if
(
!
p_vout
)
{
free_spu
(
p_sys
->
p_spu
);
free
(
p_sys
->
p_spu
);
p_sys
->
p_spu
=
NULL
;
return
;
}
#endif
vout_DisplaySubPicture
(
p_vout
,
p_sys
->
p_spu
);
}
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