Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
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-gpu
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 @@
...
@@ -7,6 +7,7 @@
*
*
* Authors: Damien LUCAS <damien.lucas@anevia.com>
* Authors: Damien LUCAS <damien.lucas@anevia.com>
* Laurent Aimar <fenrir@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@videolan.org>
*
*
* This program is free software; you can redistribute it and/or modify
* 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
* it under the terms of the GNU General Public License as published by
...
@@ -31,6 +32,8 @@
...
@@ -31,6 +32,8 @@
#include "vlc_bits.h"
#include "vlc_bits.h"
//#define DEBUG_DVBSUB 1
/*****************************************************************************
/*****************************************************************************
* Module descriptor.
* Module descriptor.
*****************************************************************************/
*****************************************************************************/
...
@@ -53,24 +56,26 @@ vlc_module_end();
...
@@ -53,24 +56,26 @@ vlc_module_end();
typedef
struct
dvbsub_rle_s
typedef
struct
dvbsub_rle_s
{
{
uint16_t
i_num
;
uint16_t
i_num
;
uint8_t
i_color_code
;
int
i_color_code
;
int
i_bpp
;
uint8_t
y
;
uint8_t
y
;
uint8_t
cr
;
uint8_t
cr
;
uint8_t
cb
;
uint8_t
cb
;
uint8_t
t
;
uint8_t
t
;
struct
dvbsub_rle_s
*
p_next
;
struct
dvbsub_rle_s
*
p_next
;
}
dvbsub_rle_t
;
}
dvbsub_rle_t
;
/* A subpicture image is a list of codes
/* A subpicture image is a list of codes
* We need to store the length of each line since nothing specify in
* 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 */
* WARNING: We assume here that a spu is less than 576 lines high */
typedef
struct
typedef
struct
{
{
uint16_t
i_rows
;
uint16_t
i_rows
;
uint16_t
i_cols
[
576
];
uint16_t
i_cols
[
576
];
dvbsub_rle_t
*
p_last
;
dvbsub_rle_t
*
p_last
;
dvbsub_rle_t
*
p_codes
;
dvbsub_rle_t
*
p_codes
;
}
dvbsub_image_t
;
}
dvbsub_image_t
;
...
@@ -80,17 +85,37 @@ typedef struct dvbsub_objectdef_s
...
@@ -80,17 +85,37 @@ typedef struct dvbsub_objectdef_s
uint16_t
i_id
;
uint16_t
i_id
;
uint8_t
i_type
;
uint8_t
i_type
;
uint8_t
i_provider
;
uint8_t
i_provider
;
uint16_t
i_xoffset
;
uint16_t
i_x
;
uint16_t
i_yoffset
;
uint16_t
i_y
;
uint8_t
i_fg_pc
;
uint8_t
i_fg_pc
;
uint8_t
i_bg_pc
;
uint8_t
i_bg_pc
;
struct
dvbsub_objectdef_s
*
p_next
;
}
dvbsub_objectdef_t
;
}
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
/* The Region is an aera on the image
* with a list of the object definitions associated
* with a list of the object definitions associated and a CLUT */
* and a CLUT */
typedef
struct
dvbsub_region_s
typedef
struct
dvbsub_region_s
{
{
uint8_t
i_id
;
uint8_t
i_id
;
...
@@ -106,7 +131,11 @@ typedef struct dvbsub_region_s
...
@@ -106,7 +131,11 @@ typedef struct dvbsub_region_s
uint8_t
i_8bp_code
;
uint8_t
i_8bp_code
;
uint8_t
i_4bp_code
;
uint8_t
i_4bp_code
;
uint8_t
i_2bp_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
;
}
dvbsub_region_t
;
...
@@ -117,23 +146,11 @@ typedef struct
...
@@ -117,23 +146,11 @@ typedef struct
uint8_t
i_timeout
;
uint8_t
i_timeout
;
uint8_t
i_state
;
uint8_t
i_state
;
uint8_t
i_version_number
;
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) */
}
dvbsub_page_t
;
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 entry in the palette CLUT */
/* The entry in the palette CLUT */
typedef
struct
typedef
struct
...
@@ -150,41 +167,26 @@ typedef struct
...
@@ -150,41 +167,26 @@ typedef struct
{
{
uint8_t
i_id
;
uint8_t
i_id
;
uint8_t
i_version_number
;
uint8_t
i_version_number
;
dvbsub_color_t
c_2b
[
0xff
];
dvbsub_color_t
c_2b
[
4
];
dvbsub_color_t
c_4b
[
0xff
];
dvbsub_color_t
c_4b
[
16
];
dvbsub_color_t
c_8b
[
0xff
];
dvbsub_color_t
c_8b
[
256
];
}
dvbsub_clut_t
;
}
dvbsub_clut_t
;
typedef
struct
typedef
struct
dvbsub_render_s
{
{
uint
8_t
i_x
;
uint
16_t
i_x
;
uint16_t
i_y
;
uint16_t
i_y
;
dvbsub_image_t
*
p_rle_top
;
dvbsub_image_t
*
p_rle_top
;
dvbsub_image_t
*
p_rle_bot
;
dvbsub_image_t
*
p_rle_bot
;
}
dvbsub_render_t
;
typedef
struct
{
int
i_id
;
mtime_t
i_pts
;
struct
dvbsub_render_s
*
p_next
;
dvbsub_clut_t
*
p_clut
[
0xff
];
}
dvbsub_render_t
;
dvbsub_page_t
*
p_page
;
dvbsub_object_t
*
p_objects
;
subpicture_t
*
p_spu
[
16
];
int
i_subpic_channel
;
}
dvbsub_all_t
;
struct
subpicture_sys_t
struct
subpicture_sys_t
{
{
mtime_t
i_pts
;
dvbsub_render_t
*
p_objects
;
/* Linked list of objects to render */
void
*
p_data
;
/* rle datas are stored */
vlc_object_t
*
p_input
;
/* Link to the input */
vlc_bool_t
b_obsolete
;
};
};
struct
decoder_sys_t
struct
decoder_sys_t
...
@@ -193,7 +195,21 @@ struct decoder_sys_t
...
@@ -193,7 +195,21 @@ struct decoder_sys_t
bs_t
bs
;
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
...
@@ -219,18 +235,27 @@ struct decoder_sys_t
#define DVBSUB_DT_28_TABLE_DATA 0x21
#define DVBSUB_DT_28_TABLE_DATA 0x21
#define DVBSUB_DT_48_TABLE_DATA 0x22
#define DVBSUB_DT_48_TABLE_DATA 0x22
#define DVBSUB_DT_END_LINE 0xf0
#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
* 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
render
(
decoder_t
*
,
vout_thread_t
*
);
static
void
decode_segment
(
decoder_t
*
,
dvbsub_all_t
*
,
bs_t
*
);
static
void
default_clut_init
(
decoder_t
*
);
static
void
render
(
dvbsub_all_t
*
,
vout_thread_t
*
);
static
void
dvbsub
(
dvbsub_all_t
*
);
/*****************************************************************************
/*****************************************************************************
* Open: probe the decoder and return score
* Open: probe the decoder and return score
...
@@ -240,8 +265,9 @@ static void dvbsub( dvbsub_all_t * );
...
@@ -240,8 +265,9 @@ static void dvbsub( dvbsub_all_t * );
*****************************************************************************/
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
p_this
)
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
;
decoder_sys_t
*
p_sys
;
int
i
;
if
(
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
'd'
,
'v'
,
'b'
,
's'
)
)
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 )
...
@@ -251,12 +277,20 @@ static int Open( vlc_object_t *p_this )
p_dec
->
pf_decode_sub
=
Decode
;
p_dec
->
pf_decode_sub
=
Decode
;
p_sys
=
p_dec
->
p_sys
=
malloc
(
sizeof
(
decoder_sys_t
)
);
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
;
p_sys
->
p_vout
=
NULL
;
p_sys
->
p_spu
=
NULL
;
init
(
&
p_sys
->
dvbsub
,
p_dec
->
fmt_in
.
subs
.
dvb
.
i_id
)
;
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'
)
);
es_format_Init
(
&
p_dec
->
fmt_out
,
SPU_ES
,
VLC_FOURCC
(
'd'
,
'v'
,
'b'
,
's'
)
);
default_clut_init
(
p_dec
);
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
...
@@ -270,7 +304,7 @@ static void Close( vlc_object_t *p_this )
...
@@ -270,7 +304,7 @@ static void Close( vlc_object_t *p_this )
if
(
p_sys
->
p_vout
&&
p_sys
->
p_vout
->
p_subpicture
!=
NULL
)
if
(
p_sys
->
p_vout
&&
p_sys
->
p_vout
->
p_subpicture
!=
NULL
)
{
{
subpicture_t
*
p_subpic
;
subpicture_t
*
p_subpic
;
int
i_subpic
;
int
i_subpic
;
for
(
i_subpic
=
0
;
i_subpic
<
VOUT_MAX_SUBPICTURES
;
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 )
...
@@ -284,8 +318,7 @@ static void Close( vlc_object_t *p_this )
}
}
}
}
dvbsub
(
&
p_sys
->
dvbsub
);
free_all
(
p_dec
);
free
(
p_sys
);
free
(
p_sys
);
}
}
...
@@ -305,120 +338,137 @@ static void Decode( decoder_t *p_dec, block_t **pp_block )
...
@@ -305,120 +338,137 @@ static void Decode( decoder_t *p_dec, block_t **pp_block )
p_block
=
*
pp_block
;
p_block
=
*
pp_block
;
*
pp_block
=
NULL
;
*
pp_block
=
NULL
;
p_sys
->
dvbsub
.
i_pts
=
p_block
->
i_pts
;
p_sys
->
i_pts
=
p_block
->
i_pts
;
if
(
p_sys
->
dvbsub
.
i_pts
<=
0
)
if
(
p_sys
->
i_pts
<=
0
)
{
{
msg_Warn
(
p_dec
,
"non dated subtitle"
);
msg_Warn
(
p_dec
,
"non dated subtitle"
);
block_Release
(
p_block
);
block_Release
(
p_block
);
return
;
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
);
bs_init
(
&
p_sys
->
bs
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
i_data_identifier
=
bs_read
(
&
p_sys
->
bs
,
8
);
if
(
bs_read
(
&
p_sys
->
bs
,
8
)
!=
0x20
)
/* Data identifier */
i_subtitle_stream_id
=
bs_read
(
&
p_sys
->
bs
,
8
);
{
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
)
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
);
vout_RegisterOSDChannel
(
p_sys
->
p_vout
);
}
}
/* Check if the page is to be displayed */
/* Check if the page is to be displayed */
if
(
p_sys
->
dvbsub
.
p_page
&&
p_sys
->
dvbsub
.
p_objects
)
if
(
p_sys
->
p_page
)
render
(
p_dec
,
p_sys
->
p_vout
);
{
render
(
&
p_sys
->
dvbsub
,
p_sys
->
p_vout
);
}
vlc_object_release
(
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
);
block_Release
(
p_block
);
}
}
/* following functions are local */
/* 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
(
;;
)
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
{
uint8_t
i
;
vout_thread_t
*
p_vout
;
if
(
p_dec
->
b_die
||
p_dec
->
b_error
)
#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;
return
NULL
;
#define RGB_TO_V(r, g, b) ((int16_t) 131 * r - 110 * g - 21 * b) / 256
;
}
p_vout
=
vlc_object_find
(
p_dec
,
VLC_OBJECT_VOUT
,
FIND_ANYWHERE
);
/* 4 entries CLUT */
if
(
p_vout
)
for
(
i
=
0
;
i
<
4
;
i
++
)
{
{
return
p_vout
;
uint8_t
R
=
0
,
G
=
0
,
B
=
0
,
T
=
0
;
}
msleep
(
VOUT_OUTMEM_SLEEP
);
}
}
static
int
init
(
dvbsub_all_t
*
p_dvbsub
,
int
i_id
)
if
(
!
(
i
&
0x2
)
&&
!
(
i
&
0x1
)
)
T
=
0xFF
;
{
else
if
(
!
(
i
&
0x2
)
&&
(
i
&
0x1
)
)
R
=
G
=
B
=
0xFF
;
int
i
;
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
;
/* 16 entries CLUT */
p_dvbsub
->
i_id
=
i_id
;
for
(
i
=
0
;
i
<
16
;
i
++
)
p_dvbsub
->
p_page
=
NULL
;
{
p_dvbsub
->
p_objects
=
NULL
;
uint8_t
R
=
0
,
G
=
0
,
B
=
0
,
T
=
0
;
for
(
i
=
0
;
i
<
255
;
i
++
)
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
)
/* 256 entries CLUT (TODO) */
{
memset
(
p_sys
->
default_clut
.
c_8b
,
0xFF
,
256
*
sizeof
(
dvbsub_color_t
)
);
free_all
(
p_dvbsub
);
}
}
static
void
decode_clut
(
dvbsub_all_t
*
p_dvbsub
,
bs_t
*
s
);
static
void
decode_segment
(
decoder_t
*
p_dec
,
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
)
{
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
int
i_type
;
int
i_type
;
int
i_page_id
;
int
i_page_id
;
int
i_size
;
int
i_size
;
/* sync_byte */
/* sync_byte
(already checked)
*/
bs_skip
(
s
,
8
);
bs_skip
(
s
,
8
);
/* segment type */
/* segment type */
...
@@ -430,45 +480,66 @@ static void decode_segment( decoder_t *p_dec, dvbsub_all_t *p_dvbspu, bs_t *s )
...
@@ -430,45 +480,66 @@ static void decode_segment( decoder_t *p_dec, dvbsub_all_t *p_dvbspu, bs_t *s )
/* segment size */
/* segment size */
i_size
=
bs_show
(
s
,
16
);
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
)
);
bs_skip
(
s
,
8
*
(
2
+
i_size
)
);
return
;
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
)
switch
(
i_type
)
{
{
case
DVBSUB_ST_
CLUT_DEFIN
ITION
:
case
DVBSUB_ST_
PAGE_COMPOS
ITION
:
#ifdef DEBUG_DVBSUB
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"
subtitle dvbsub_decode_clut
"
);
msg_Dbg
(
p_dec
,
"
decode_page_composition
"
);
#endif
#endif
decode_
clut
(
p_dvbspu
,
s
);
decode_
page_composition
(
p_dec
,
s
);
break
;
break
;
case
DVBSUB_ST_PAGE_COMPOSITION
:
case
DVBSUB_ST_REGION_COMPOSITION
:
#ifdef DEBUG_DVBSUB
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"
subtitle dvbsub_decode_page
_composition"
);
msg_Dbg
(
p_dec
,
"
decode_region
_composition"
);
#endif
#endif
decode_
page_composition
(
p_dvbspu
,
s
);
decode_
region_composition
(
p_dec
,
s
);
break
;
break
;
case
DVBSUB_ST_REGION_COMPOSITION
:
case
DVBSUB_ST_CLUT_DEFINITION
:
#ifdef DEBUG_DVBSUB
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"
subtitle dvbsub_decode_region_composition
"
);
msg_Dbg
(
p_dec
,
"
decode_clut
"
);
#endif
#endif
decode_
region_composition
(
p_dvbspu
,
s
);
decode_
clut
(
p_dec
,
s
);
break
;
break
;
case
DVBSUB_ST_OBJECT_DATA
:
case
DVBSUB_ST_OBJECT_DATA
:
#ifdef DEBUG_DVBSUB
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"
subtitle dvbsub_
decode_object"
);
msg_Dbg
(
p_dec
,
"decode_object"
);
#endif
#endif
decode_object
(
p_d
vbspu
,
s
);
decode_object
(
p_d
ec
,
s
);
break
;
break
;
case
DVBSUB_ST_ENDOFDISPLAY
:
case
DVBSUB_ST_ENDOFDISPLAY
:
#ifdef DEBUG_DVBSUB
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"
subtitle dvbsub_stop_
display"
);
msg_Dbg
(
p_dec
,
"
end of
display"
);
#endif
#endif
stop_display
(
p_dvbspu
);
bs_skip
(
s
,
8
*
(
2
+
i_size
)
);
break
;
break
;
case
DVBSUB_ST_STUFFING
:
case
DVBSUB_ST_STUFFING
:
#ifdef DEBUG_DVBSUB
msg_Dbg
(
p_dec
,
"skip stuffing"
);
#endif
bs_skip
(
s
,
8
*
(
2
+
i_size
)
);
break
;
default:
default:
msg_Warn
(
p_dec
,
"unsupported segment type: (%04x)"
,
i_type
);
msg_Warn
(
p_dec
,
"unsupported segment type: (%04x)"
,
i_type
);
bs_skip
(
s
,
8
*
(
2
+
i_size
)
);
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 )
...
@@ -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
)
static
void
decode_clut
(
decoder_t
*
p_dec
,
bs_t
*
s
)
{
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
)
{
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
uint16_t
i_segment_length
;
uint16_t
i_segment_length
;
uint16_t
i_processed_length
;
uint16_t
i_processed_length
;
dvbsub_clut_t
*
clut
;
dvbsub_clut_t
*
p_
clut
;
uint8_t
i_clut_id
;
uint8_t
i_clut_id
;
uint8_t
i_version_number
;
uint8_t
i_version_number
;
...
@@ -498,29 +560,25 @@ static void decode_clut( dvbsub_all_t *p_dvbsub, bs_t *s )
...
@@ -498,29 +560,25 @@ static void decode_clut( dvbsub_all_t *p_dvbsub, bs_t *s )
i_clut_id
=
bs_read
(
s
,
8
);
i_clut_id
=
bs_read
(
s
,
8
);
i_version_number
=
bs_read
(
s
,
4
);
i_version_number
=
bs_read
(
s
,
4
);
/
/ Check that this id doesn't not already exist
/
* Check that this id doesn't not already exist with the same version
// with the same version number
* number and allocate memory if necessary */
// And allocate memory if necessary
if
(
p_sys
->
p_clut
[
i_clut_id
]
!=
NULL
&&
if
(
p_dvbsub
->
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
)
/* Nothing to do */
{
bs_skip
(
s
,
8
*
i_segment_length
-
12
);
//TODO skip the right number of bits
return
;
return
;
}
}
else
{
if
(
!
p_sys
->
p_clut
[
i_clut_id
]
)
memset
(
p_dvbsub
->
p_clut
[
i_clut_id
],
0
,
sizeof
(
dvbsub_clut_t
)
);
}
}
else
{
{
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 */
/* 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 */
bs_skip
(
s
,
4
);
/* Reserved bits */
i_processed_length
=
2
;
i_processed_length
=
2
;
while
(
i_processed_length
<
i_segment_length
)
while
(
i_processed_length
<
i_segment_length
)
...
@@ -552,119 +610,162 @@ static void decode_clut( dvbsub_all_t *p_dvbsub, bs_t *s )
...
@@ -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
/* According to EN 300-743 section 7.2.3 note 1, type should
* not have more than 1 bit set to one
* not have more than 1 bit set to one
, but some strams don't
But, some strams don't
respect this note. */
*
respect this note. */
if
(
i_type
&
0x04
)
if
(
i_type
&
0x04
)
{
{
clut
->
c_2b
[
i_id
].
Y
=
y
;
p_
clut
->
c_2b
[
i_id
].
Y
=
y
;
clut
->
c_2b
[
i_id
].
Cr
=
cr
;
p_
clut
->
c_2b
[
i_id
].
Cr
=
cr
;
clut
->
c_2b
[
i_id
].
Cb
=
cb
;
p_
clut
->
c_2b
[
i_id
].
Cb
=
cb
;
clut
->
c_2b
[
i_id
].
T
=
t
;
p_
clut
->
c_2b
[
i_id
].
T
=
t
;
}
}
if
(
i_type
&
0x02
)
if
(
i_type
&
0x02
)
{
{
clut
->
c_4b
[
i_id
].
Y
=
y
;
p_
clut
->
c_4b
[
i_id
].
Y
=
y
;
clut
->
c_4b
[
i_id
].
Cr
=
cr
;
p_
clut
->
c_4b
[
i_id
].
Cr
=
cr
;
clut
->
c_4b
[
i_id
].
Cb
=
cb
;
p_
clut
->
c_4b
[
i_id
].
Cb
=
cb
;
clut
->
c_4b
[
i_id
].
T
=
t
;
p_
clut
->
c_4b
[
i_id
].
T
=
t
;
}
}
if
(
i_type
&
0x01
)
if
(
i_type
&
0x01
)
{
{
clut
->
c_8b
[
i_id
].
Y
=
y
;
p_
clut
->
c_8b
[
i_id
].
Y
=
y
;
clut
->
c_8b
[
i_id
].
Cr
=
cr
;
p_
clut
->
c_8b
[
i_id
].
Cr
=
cr
;
clut
->
c_8b
[
i_id
].
Cb
=
cb
;
p_
clut
->
c_8b
[
i_id
].
Cb
=
cb
;
clut
->
c_8b
[
i_id
].
T
=
t
;
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_version_number
;
unsigned
int
i_state
;
unsigned
int
i_state
;
unsigned
int
i_segment_length
;
unsigned
int
i_segment_length
;
uint8_t
i_timeout
;
uint8_t
i_timeout
;
unsigned
int
i
;
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_timeout
=
bs_read
(
s
,
8
);
i_version_number
=
bs_read
(
s
,
4
);
i_version_number
=
bs_read
(
s
,
4
);
i_state
=
bs_read
(
s
,
2
);
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 */
bs_skip
(
s
,
2
);
/* Reserved */
/* Allocate a new page */
if
(
i_state
==
DVBSUB_PCS_STATE_CHANGE
)
p_dvbsub
->
p_page
=
malloc
(
sizeof
(
dvbsub_page_t
)
);
{
p_dvbsub
->
p_page
->
i_timeout
=
i_timeout
;
/* 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: */
if
(
i_state
==
DVBSUB_PCS_STATE_ACQUISITION
)
p_dvbsub
->
p_page
->
i_regions_number
=
(
i_segment_length
-
2
)
/
6
;
{
/* 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
if
(
!
p_sys
->
p_page
)
* instead of a 0x80 packet (End Of Display) */
if
(
p_dvbsub
->
p_page
->
i_regions_number
==
0
)
{
{
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
=
p_sys
->
p_page
->
i_version_number
=
i_version_number
;
malloc
(
p_dvbsub
->
p_page
->
i_regions_number
*
sizeof
(
dvbsub_region_t
)
);
p_sys
->
p_page
->
i_timeout
=
i_timeout
;
for
(
i
=
0
;
i
<
p_dvbsub
->
p_page
->
i_regions_number
;
i
++
)
/* 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 */
bs_skip
(
s
,
8
);
/* Reserved */
p_dvbsub
->
p_page
->
regions
[
i
].
i_x
=
bs_read
(
s
,
16
);
p_sys
->
p_page
->
p_region_defs
[
i
].
i_x
=
bs_read
(
s
,
16
);
p_dvbsub
->
p_page
->
regions
[
i
].
i_y
=
bs_read
(
s
,
16
);
p_sys
->
p_page
->
p_region_defs
[
i
].
i_y
=
bs_read
(
s
,
16
);
p_dvbsub
->
p_page
->
regions
[
i
].
p_object
=
NULL
;
#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
(
decoder_t
*
p_dec
,
bs_t
*
s
)
static
void
decode_region_composition
(
dvbsub_all_t
*
p_dvbsub
,
bs_t
*
s
)
{
{
dvbsub_region_t
*
p_region
=
NULL
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
unsigned
int
i_segment_length
;
dvbsub_region_t
*
p_region
,
**
pp_region
=
&
p_sys
->
p_regions
;
unsigned
int
i_processed_length
;
int
i_segment_length
;
unsigned
int
i_region_id
;
int
i_processed_length
;
unsigned
int
i
;
int
i_region_id
;
int
i_version_number
;
i_segment_length
=
bs_read
(
s
,
16
);
i_segment_length
=
bs_read
(
s
,
16
);
/* Get region id: */
i_region_id
=
bs_read
(
s
,
8
);
i_region_id
=
bs_read
(
s
,
8
);
for
(
i
=
0
;
i
<
p_dvbsub
->
p_page
->
i_regions_number
;
i
++
)
i_version_number
=
bs_read
(
s
,
4
);
{
if
(
p_dvbsub
->
p_page
->
regions
[
i
].
i_id
==
i_region_id
)
/* 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
bs_skip
(
s
,
8
*
(
i_segment_length
-
1
)
-
4
);
* The region has never been declared before
* Internal error */
fprintf
(
stderr
,
"Decoding of undeclared region N/A
\n
"
);
return
;
return
;
}
}
else
if
(
p_region
)
{
if
(
p_region
->
i_object_defs
)
free
(
p_region
->
p_object_defs
);
}
/* Skip version number and fill flag */
if
(
!
p_region
)
if
(
bs_show
(
s
,
4
)
==
p_region
->
i_version_number
)
{
{
fprintf
(
stderr
,
"Skipping already known region N/A
\n
"
);
#ifdef DEBUG_DVBSUB
/* TODO Skip the right number of bits */
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 */
/* 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
);
p_region
->
b_fill
=
bs_read
(
s
,
1
);
bs_skip
(
s
,
3
);
/* Reserved */
bs_skip
(
s
,
3
);
/* Reserved */
p_region
->
i_width
=
bs_read
(
s
,
16
);
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 )
...
@@ -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_4bp_code
=
bs_read
(
s
,
4
);
p_region
->
i_2bp_code
=
bs_read
(
s
,
2
);
p_region
->
i_2bp_code
=
bs_read
(
s
,
2
);
bs_skip
(
s
,
2
);
/* Reserved */
bs_skip
(
s
,
2
);
/* Reserved */
p_region
->
p_object_defs
=
NULL
;
p_region
->
i_object_defs
=
0
;
/* List of objects in the region: */
/* List of objects in the region */
/* We already skipped 10 bytes */
i_processed_length
=
10
;
i_processed_length
=
10
;
while
(
i_processed_length
<
i_segment_length
)
while
(
i_processed_length
<
i_segment_length
)
{
{
dvbsub_objectdef_t
*
p_obj
;
/* We create a new object */
/* 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 */
/* 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_id
=
bs_read
(
s
,
16
);
p_obj
->
i_type
=
bs_read
(
s
,
2
);
p_obj
->
i_type
=
bs_read
(
s
,
2
);
p_obj
->
i_provider
=
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 */
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
;
i_processed_length
+=
6
;
...
@@ -705,48 +811,67 @@ static void decode_region_composition( dvbsub_all_t *p_dvbsub, bs_t *s )
...
@@ -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
);
p_obj
->
i_bg_pc
=
bs_read
(
s
,
8
);
i_processed_length
+=
2
;
i_processed_length
+=
2
;
}
}
}
}
/* we append it */
static
dvbsub_image_t
*
dvbsub_parse_pdata
(
decoder_t
*
,
bs_t
*
,
uint16_t
);
if
(
p_region
->
p_object
)
static
uint16_t
dvbsub_pdata2bpp
(
bs_t
*
,
uint16_t
*
,
dvbsub_image_t
*
);
{
static
uint16_t
dvbsub_pdata4bpp
(
bs_t
*
,
uint16_t
*
,
dvbsub_image_t
*
);
dvbsub_objectdef_t
*
p_o
;
static
uint16_t
dvbsub_pdata8bpp
(
bs_t
*
,
uint16_t
*
,
dvbsub_image_t
*
);
for
(
p_o
=
p_region
->
p_object
;
;
p_o
=
p_o
->
p_next
)
{
static
void
decode_object
(
decoder_t
*
p_dec
,
bs_t
*
s
)
if
(
p_o
->
p_next
==
NULL
)
{
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 */
if
(
!
p_obj
)
p_obj
=
malloc
(
sizeof
(
dvbsub_object_t
)
);
{
#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
;
p_obj
->
p_next
=
NULL
;
}
i_segment_length
=
bs_read
(
s
,
16
);
p_obj
->
i_id
=
i_obj_id
;
p_obj
->
i_version_number
=
i_version_number
;
/* TODO Check we don't already have this object / this version */
p_obj
->
i_coding_method
=
i_coding_method
;
p_obj
->
i_id
=
bs_read
(
s
,
16
);
p_obj
->
b_non_modify_color
=
bs_read
(
s
,
1
);
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
);
bs_skip
(
s
,
1
);
/* Reserved */
bs_skip
(
s
,
1
);
/* Reserved */
if
(
p_obj
->
i_coding_method
==
0x00
)
if
(
p_obj
->
i_coding_method
==
0x00
)
...
@@ -758,22 +883,17 @@ static void decode_object( dvbsub_all_t *p_dvbsub, bs_t *s )
...
@@ -758,22 +883,17 @@ static void decode_object( dvbsub_all_t *p_dvbsub, bs_t *s )
i_bottomfield_length
=
bs_read
(
s
,
16
);
i_bottomfield_length
=
bs_read
(
s
,
16
);
p_obj
->
topfield
=
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
=
p_obj
->
bottomfield
=
dvbsub_parse_pdata
(
p_d
vbsub
,
s
,
i_bottomfield_length
);
dvbsub_parse_pdata
(
p_d
ec
,
s
,
i_bottomfield_length
);
}
}
else
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
)
uint16_t
length
)
{
{
dvbsub_image_t
*
p_image
;
dvbsub_image_t
*
p_image
;
...
@@ -789,31 +909,29 @@ static dvbsub_image_t* dvbsub_parse_pdata( dvbsub_all_t *p_dvbsub, bs_t *s,
...
@@ -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 */
/* Let's parse it a first time to determine the size of the buffer */
while
(
i_processed_length
<
length
)
while
(
i_processed_length
<
length
)
{
{
i_processed_length
++
;
switch
(
bs_read
(
s
,
8
)
)
switch
(
bs_read
(
s
,
8
)
)
{
{
case
0x10
:
case
0x10
:
fprintf
(
stderr
,
"0x10 N/A
\n
"
);
i_processed_length
+=
dvbsub_pdata2bpp
(
s
,
&
p_image
->
i_cols
[
i_lines
],
p_image
);
break
;
break
;
case
0x11
:
case
0x11
:
i_processed_length
+=
i_processed_length
+=
1
+
dvbsub_count0x11
(
s
,
&
(
p_image
->
i_cols
[
i_lines
]),
dvbsub_pdata4bpp
(
s
,
&
p_image
->
i_cols
[
i_lines
],
p_image
);
p_image
);
break
;
break
;
case
0x12
:
case
0x12
:
fprintf
(
stderr
,
"0x12 N/A
\n
"
);
i_processed_length
+=
dvbsub_pdata8bpp
(
s
,
&
p_image
->
i_cols
[
i_lines
],
p_image
);
break
;
break
;
case
0x20
:
case
0x20
:
fprintf
(
stderr
,
"0x20 N/A
\n
"
);
break
;
case
0x21
:
case
0x21
:
fprintf
(
stderr
,
"0x21 N/A
\n
"
);
break
;
case
0x22
:
case
0x22
:
fprintf
(
stderr
,
"0x22 N/A
\n
"
);
/* We don't use map tables */
break
;
break
;
case
0xf0
:
case
0xf0
:
i_processed_length
++
;
i_lines
++
;
/* End of line code */
i_lines
++
;
break
;
break
;
}
}
}
}
...
@@ -830,9 +948,10 @@ static dvbsub_image_t* dvbsub_parse_pdata( dvbsub_all_t *p_dvbsub, bs_t *s,
...
@@ -830,9 +948,10 @@ static dvbsub_image_t* dvbsub_parse_pdata( dvbsub_all_t *p_dvbsub, bs_t *s,
return
p_image
;
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_next
=
malloc
(
sizeof
(
dvbsub_rle_t
)
);
p
->
p_last
=
p
->
p_last
->
p_next
;
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 )
...
@@ -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
=
p
->
p_codes
;
}
}
p
->
p_last
->
i_num
=
num
;
p
->
p_last
->
i_num
=
num
;
p
->
p_last
->
i_color_code
=
color
;
p
->
p_last
->
i_color_code
=
color
;
p
->
p_last
->
i_bpp
=
i_bpp
;
p
->
p_last
->
p_next
=
NULL
;
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
)
dvbsub_image_t
*
p_image
)
{
{
uint16_t
i_processed
=
0
;
uint16_t
i_processed
=
0
;
vlc_bool_t
b_stop
=
0
;
vlc_bool_t
b_stop
=
0
;
uint16_t
i_count
=
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
)
if
(
(
i_color
=
bs_read
(
s
,
4
))
!=
0x00
)
{
{
(
*
p
)
++
;
(
*
p
)
++
;
i_processed
+=
4
;
i_processed
+=
4
;
/*
1 pixel of color code '0000'
*/
/*
Add 1 pixel
*/
add_rle_code
(
p_image
,
1
,
i_color
);
add_rle_code
(
p_image
,
1
,
i_color
,
4
);
}
}
else
else
{
{
...
@@ -873,7 +1064,7 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
...
@@ -873,7 +1064,7 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
{
{
i_count
=
2
+
bs_read
(
s
,
3
);
i_count
=
2
+
bs_read
(
s
,
3
);
(
*
p
)
+=
i_count
;
(
*
p
)
+=
i_count
;
add_rle_code
(
p_image
,
i_count
,
0x00
);
add_rle_code
(
p_image
,
i_count
,
0x00
,
4
);
}
}
else
else
{
{
...
@@ -890,7 +1081,7 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
...
@@ -890,7 +1081,7 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
i_color
=
bs_read
(
s
,
4
);
i_color
=
bs_read
(
s
,
4
);
(
*
p
)
+=
i_count
;
(
*
p
)
+=
i_count
;
i_processed
+=
12
;
i_processed
+=
12
;
add_rle_code
(
p_image
,
i_count
,
i_color
);
add_rle_code
(
p_image
,
i_count
,
i_color
,
4
);
}
}
else
else
{
{
...
@@ -899,26 +1090,26 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
...
@@ -899,26 +1090,26 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
case
0x0
:
case
0x0
:
(
*
p
)
++
;
(
*
p
)
++
;
i_processed
+=
8
;
i_processed
+=
8
;
add_rle_code
(
p_image
,
1
,
0x00
);
add_rle_code
(
p_image
,
1
,
0x00
,
4
);
break
;
break
;
case
0x1
:
case
0x1
:
(
*
p
)
+=
2
;
(
*
p
)
+=
2
;
i_processed
+=
8
;
i_processed
+=
8
;
add_rle_code
(
p_image
,
2
,
0x00
);
add_rle_code
(
p_image
,
2
,
0x00
,
4
);
break
;
break
;
case
0x2
:
case
0x2
:
i_count
=
9
+
bs_read
(
s
,
4
);
i_count
=
9
+
bs_read
(
s
,
4
);
i_color
=
bs_read
(
s
,
4
);
i_color
=
bs_read
(
s
,
4
);
(
*
p
)
+=
i_count
;
(
*
p
)
+=
i_count
;
i_processed
+=
16
;
i_processed
+=
16
;
add_rle_code
(
p_image
,
i_count
,
i_color
);
add_rle_code
(
p_image
,
i_count
,
i_color
,
4
);
break
;
break
;
case
0x3
:
case
0x3
:
i_count
=
25
+
bs_read
(
s
,
8
);
i_count
=
25
+
bs_read
(
s
,
8
);
i_color
=
bs_read
(
s
,
4
);
i_color
=
bs_read
(
s
,
4
);
(
*
p
)
+=
i_count
;
(
*
p
)
+=
i_count
;
i_processed
+=
20
;
i_processed
+=
20
;
add_rle_code
(
p_image
,
i_count
,
i_color
);
add_rle_code
(
p_image
,
i_count
,
i_color
,
4
);
break
;
break
;
}
}
}
}
...
@@ -931,98 +1122,157 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
...
@@ -931,98 +1122,157 @@ static uint16_t dvbsub_count0x11( bs_t *s, uint16_t* p,
return
(
i_processed
+
7
)
/
8
;
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
;
uint16_t
i_processed
=
0
;
dvbsub_rle_t
*
p2
=
NULL
;
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
;
bs_skip
(
s
,
7
);
free
(
p1
);
b_stop
=
1
;
p1
=
NULL
;
}
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
)
return
(
i_processed
+
7
)
/
8
;
{
free
(
p_o
);
}
}
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_image_t
*
p_image
=
malloc
(
sizeof
(
dvbsub_image_t
)
);
dvbsub_objectdef_t
*
p2
=
NULL
;
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
;
dvbsub_rle_t
*
p_last
=
p_image
->
p_last
;
free
(
p1
);
p_image
->
p_last
=
malloc
(
sizeof
(
dvbsub_rle_t
)
);
p1
=
NULL
;
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_i
);
free
(
p_r
);
p_r
=
NULL
;
}
}
static
void
free_
objects
(
dvbsub_object_t
*
p_o
)
static
void
free_
spu
(
subpicture_t
*
p_spu
)
{
{
dvbsub_object_t
*
p1
;
dvbsub_render_t
*
p_obj
,
*
p_obj_next
;
dvbsub_object_t
*
p2
=
NULL
;
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
;
p
_obj_next
=
p_obj
->
p_next
;
free_image
(
p1
->
topfield
);
free_image
(
p_obj
->
p_rle_top
);
free_image
(
p1
->
bottomfield
);
free_image
(
p_obj
->
p_rle_bot
);
free
_object
(
p1
);
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
)
for
(
p_obj
=
p_sys
->
p_objects
;
p_obj
!=
NULL
;
p_obj
=
p_obj_next
)
{
{
free_regions
(
p_p
->
regions
,
p_p
->
i_regions_number
);
p_obj_next
=
p_obj
->
p_next
;
free
(
p_p
);
free_image
(
p_obj
->
topfield
);
p_p
=
NULL
;
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
);
if
(
p_sys
->
p_clut
[
i
]
)
free
(
p_sys
->
p_clut
[
i
]
);
free_image
(((
dvbsub_render_t
*
)
p_spu
->
p_sys
->
p_data
)
->
p_rle_bot
);
p_sys
->
p_clut
[
i
]
=
NULL
;
free
(
p_spu
->
p_sys
->
p_data
);
free
(
p_spu
->
p_sys
);
p_spu
->
p_sys
=
NULL
;
}
}
}
static
void
free_all
(
dvbsub_all_t
*
p_a
)
if
(
p_sys
->
p_page
)
{
{
unsigned
int
i
;
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
(
p_reg
=
p_sys
->
p_regions
;
p_reg
!=
NULL
;
p_reg
=
p_reg_next
)
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
);
p_reg_next
=
p_reg
->
p_next
;
free_objects
(
p_a
->
p_objects
);
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
,
static
void
RenderYUY2
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
,
const
subpicture_t
*
p_spu
)
dvbsub_render_t
*
p_r
)
{
{
/* Common variables */
/* Common variables */
uint8_t
*
p_desty
;
uint8_t
*
p_desty
;
...
@@ -1030,7 +1280,6 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
...
@@ -1030,7 +1280,6 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
uint16_t
i_cnt
;
uint16_t
i_cnt
;
uint16_t
x
,
y
;
uint16_t
x
,
y
;
dvbsub_rle_t
*
p_c
;
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
;
dvbsub_image_t
*
p_im
=
p_r
->
p_rle_top
;
i
=
0
;
i
=
0
;
j
=
0
;
j
=
0
;
...
@@ -1088,76 +1337,77 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
...
@@ -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
,
static
void
RenderI42x
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
,
const
subpicture_t
*
p_spu
)
dvbsub_render_t
*
p_r
)
{
{
/* Common variables */
/* Common variables */
uint8_t
*
p_desty
;
uint8_t
*
p_desty
=
p_pic
->
Y_PIXELS
;
uint8_t
*
p_destu
;
uint8_t
*
p_destu
=
p_pic
->
U_PIXELS
;
uint8_t
*
p_destv
;
uint8_t
*
p_destv
=
p_pic
->
V_PIXELS
;
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
);
dvbsub_image_t
*
p_im
=
p_r
->
p_rle_top
;
dvbsub_image_t
*
p_im
=
p_r
->
p_rle_top
;
i
=
0
;
dvbsub_rle_t
*
p_c
;
j
=
0
;
uint16_t
i
,
j
,
x
,
y
;
p_desty
=
p_pic
->
Y_PIXELS
;
int
i_x_subsampling
=
p_destu
=
p_pic
->
U_PIXELS
;
p_vout
->
output
.
i_chroma
==
VLC_FOURCC
(
'I'
,
'4'
,
'2'
,
'2'
)
?
1
:
2
;
p_destv
=
p_pic
->
V_PIXELS
;
//let's render the 1st frame
/* Let's render the top field */
for
(
p_c
=
p_im
->
p_codes
;
p_c
->
p_next
!=
NULL
;
p_c
=
p_c
->
p_next
)
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
;
x
=
j
+
p_r
->
i_x
;
y
=
2
*
i
+
p_r
->
i_y
;
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
->
y
,
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
/
2
*
p_pic
->
U_PITCH
+
x
/
i_x_subsampling
,
//memset(p_destu+ (y)*p_pic->Y_PITCH + x, p_c->cb, p_c->i_num);
p_c
->
cr
,
p_c
->
i_num
/
i_x_subsampling
);
memset
(
p_desty
+
y
*
p_pic
->
Y_PITCH
+
x
,
p_c
->
y
,
p_c
->
i_num
);
memset
(
p_destv
+
y
/
2
*
p_pic
->
V_PITCH
+
x
/
i_x_subsampling
,
//memset(p_desty+ 2*y*p_pic->U_PITCH + x, p_c->cr, p_c->i_num);
p_c
->
cb
,
p_c
->
i_num
/
i_x_subsampling
);
//memset(p_desty+ 2*y*p_pic->V_PITCH + x, p_c->cb, p_c->i_num);
}
}
j
+=
p_c
->
i_num
;
j
+=
p_c
->
i_num
;
if
(
j
>=
p_im
->
i_cols
[
i
]
)
if
(
j
>=
p_im
->
i_cols
[
i
]
)
{
{
i
++
;
j
=
0
;
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
;
/* Idem for the bottom field */
for
(
p_c
=
p_im
->
p_codes
;
p_c
->
p_next
!=
NULL
;
p_c
=
p_c
->
p_next
)
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
;
x
=
j
+
p_r
->
i_x
;
y
=
2
*
i
+
1
+
p_r
->
i_y
;
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);
memset
(
p_desty
+
y
*
p_pic
->
Y_PITCH
+
x
,
p_c
->
y
,
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);
/
* No U or V (decimation) */
}
}
j
+=
p_c
->
i_num
;
j
+=
p_c
->
i_num
;
if
(
j
>=
p_im
->
i_cols
[
i
]
)
if
(
j
>=
p_im
->
i_cols
[
i
]
)
{
{
i
++
;
j
=
0
;
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
,
static
void
RenderDVBSUB
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
,
const
subpicture_t
*
p_spu
)
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
)
switch
(
p_vout
->
output
.
i_chroma
)
{
{
...
@@ -1169,7 +1419,7 @@ static void RenderDVBSUB( vout_thread_t *p_vout, picture_t *p_pic,
...
@@ -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
/* 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
* to I420. Remember to change it the day we'll take into account
* U and V info. */
* U and V info. */
RenderI42x
(
p_vout
,
p_pic
,
p_
spu
);
RenderI42x
(
p_vout
,
p_pic
,
p_
render
);
break
;
break
;
/* RV16 target, scaling */
/* RV16 target, scaling */
...
@@ -1187,123 +1437,154 @@ static void RenderDVBSUB( vout_thread_t *p_vout, picture_t *p_pic,
...
@@ -1187,123 +1437,154 @@ static void RenderDVBSUB( vout_thread_t *p_vout, picture_t *p_pic,
/* NVidia overlay, no scaling */
/* NVidia overlay, no scaling */
case
VLC_FOURCC
(
'Y'
,
'U'
,
'Y'
,
'2'
):
case
VLC_FOURCC
(
'Y'
,
'U'
,
'Y'
,
'2'
):
RenderYUY2
(
p_vout
,
p_pic
,
p_
spu
);
RenderYUY2
(
p_vout
,
p_pic
,
p_
render
);
break
;
break
;
default:
default:
msg_Err
(
p_vout
,
"unknown chroma, can't render SPU"
);
msg_Err
(
p_vout
,
"unknown chroma, can't render SPU"
);
break
;
break
;
}
}
}
static
void
dvbsub_Destroy
(
subpicture_t
*
p_spu
)
p_render
=
p_render
->
p_next
;
{
}
free_spu
(
p_spu
);
}
}
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
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
dvbsub_objectdef_t
*
p_objectdef
;
dvbsub_render_t
*
p_render
=
NULL
,
*
p_current
,
*
p_last
=
NULL
;
dvbsub_object_t
*
p_o
;
dvbsub_clut_t
*
p_clut
;
dvbsub_object_t
*
p_object
;
dvbsub_rle_t
*
p_c
;
dvbsub_object_t
*
p_object_old
;
int
i
,
j
=
0
,
i_timeout
=
0
;
dvbsub_render_t
*
p_render
;
dvbsub_rle_t
*
p_c
;
/* Allocate the subpicture internal data. */
uint8_t
i
,
j
=
0
;
#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 */
if
(
!
p_region
)
for
(
i
=
0
;
i
<
dvbsub
->
p_page
->
i_regions_number
;
i
++
)
{
{
p_region
=
&
(
dvbsub
->
p_page
->
regions
[
i
]);
msg_Err
(
p_dec
,
"no region founddddd!!!"
);
continue
;
}
/* loop on objects */
/* Loop on object definitions */
for
(
p_objectdef
=
p_region
->
p_object
;
p_objectdef
!=
NULL
;
for
(
j
=
0
;
j
<
p_region
->
i_object_defs
;
j
++
)
p_objectdef
=
p_objectdef
->
p_next
)
{
{
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 */
/* Look for the right object */
p_object
=
dvbsub
->
p_objects
;
for
(
p_object
=
p_sys
->
p_objects
;
p_object
!=
NULL
;
while
(
!
p_object
&&
p_object
->
i_id
!=
p_objectdef
->
i_id
)
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
)
if
(
!
p_object
)
{
{
msg_Err
(
p_
vout
,
"internal decoder error"
);
msg_Err
(
p_
dec
,
"no object founddddd!!!"
);
return
;
continue
;
}
}
/* Allocate the render structure */
/* Allocate the render structure */
p_render
=
malloc
(
sizeof
(
dvbsub_render_t
)
);
p_current
=
malloc
(
sizeof
(
dvbsub_render_t
)
);
p_render
->
i_x
=
p_region
->
i_x
+
p_objectdef
->
i_xoffset
;
p_current
->
p_next
=
NULL
;
p_render
->
i_y
=
p_region
->
i_y
+
p_objectdef
->
i_yoffset
;
p_current
->
i_x
=
p_regiondef
->
i_x
+
p_objectdef
->
i_x
;
p_render
->
p_rle_top
=
p_object
->
topfield
;
p_current
->
i_y
=
p_regiondef
->
i_y
+
p_objectdef
->
i_y
;
p_render
->
p_rle_bot
=
p_object
->
bottomfield
;
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
p_clut
=
p_sys
->
p_clut
[
p_region
->
i_clut
];
if
(
!
dvbsub
->
p_clut
[
p_region
->
i_clut
]
)
return
;
if
(
!
p_clut
)
p_clut
=
&
p_sys
->
default_clut
;
/* Compute the color datas according to the appropriate 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
)
p_c
->
p_next
!=
NULL
;
p_c
=
p_c
->
p_next
)
{
{
//TODO We assume here we are working in 4bp
dvbsub_color_t
*
p_color
=
(
p_c
->
i_bpp
==
2
)
?
p_clut
->
c_2b
:
p_c
->
y
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
Y
;
(
p_c
->
i_bpp
==
4
)
?
p_clut
->
c_4b
:
p_clut
->
c_8b
;
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
->
y
=
p_color
[
p_c
->
i_color_code
].
Y
;
p_c
->
t
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
T
;
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
)
p_c
=
p_c
->
p_next
)
{
{
//TODO We assume here we are working in 4bp
dvbsub_color_t
*
p_color
=
(
p_c
->
i_bpp
==
2
)
?
p_clut
->
c_2b
:
p_c
->
y
=
dvbsub
->
p_clut
[
p_region
->
i_clut
]
->
c_4b
[
p_c
->
i_color_code
].
Y
;
(
p_c
->
i_bpp
==
4
)
?
p_clut
->
c_4b
:
p_clut
->
c_8b
;
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
;
}
/* Allocate the subpicture internal data. */
p_c
->
y
=
p_color
[
p_c
->
i_color_code
].
Y
;
dvbsub
->
p_spu
[
j
]
=
p_c
->
cr
=
p_color
[
p_c
->
i_color_code
].
Cr
;
vout_CreateSubPicture
(
p_vout
,
dvbsub
->
i_subpic_channel
,
p_c
->
cb
=
p_color
[
p_c
->
i_color_code
].
Cb
;
MEMORY_SUBPICTURE
);
p_c
->
t
=
p_color
[
p_c
->
i_color_code
].
T
;
if
(
dvbsub
->
p_spu
[
j
]
==
NULL
)
{
msg_Err
(
p_vout
,
"Unable to allocate memory, skipping"
);
return
;
}
}
/* 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