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
82ca25cb
Commit
82ca25cb
authored
Nov 22, 2003
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* all: ported to new API.
-> i_rate isn't used for now : it will need to be fixed.
parent
1a80449a
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
306 additions
and
354 deletions
+306
-354
modules/codec/spudec/parse.c
modules/codec/spudec/parse.c
+100
-190
modules/codec/spudec/render.c
modules/codec/spudec/render.c
+1
-2
modules/codec/spudec/spudec.c
modules/codec/spudec/spudec.c
+187
-127
modules/codec/spudec/spudec.h
modules/codec/spudec/spudec.h
+18
-35
No files found.
modules/codec/spudec/parse.c
View file @
82ca25cb
...
...
@@ -2,9 +2,10 @@
* parse.c: SPU parser
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: parse.c,v 1.1
3 2003/07/29 22:25:40 gbazin
Exp $
* $Id: parse.c,v 1.1
4 2003/11/22 19:55:47 fenrir
Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Laurent Aimar <fenrir@via.ecp.fr>
*
* 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
...
...
@@ -25,19 +26,19 @@
* Preamble
*****************************************************************************/
#include <stdlib.h>
/* malloc(), free() */
#include <string.h>
/* memcpy(), memset() */
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/decoder.h>
#include <vlc/input.h>
#include "spudec.h"
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
static
int
ParseControlSeq
(
spudec_thread
_t
*
,
subpicture_t
*
);
static
int
ParseRLE
(
spudec_thread_t
*
,
subpicture_t
*
,
uint8
_t
*
);
static
int
ParseControlSeq
(
decoder
_t
*
,
subpicture_t
*
);
static
int
ParseRLE
(
decoder_t
*
,
subpicture
_t
*
);
static
void
DestroySPU
(
subpicture_t
*
);
...
...
@@ -61,62 +62,20 @@ static inline unsigned int AddNibble( unsigned int i_code,
}
}
/*****************************************************************************
* SyncPacket: get in sync with the stream
*****************************************************************************
* This function makes a few sanity checks and returns 0 if it looks like we
* are at the beginning of a subpicture packet.
*****************************************************************************/
int
E_
(
SyncPacket
)(
spudec_thread_t
*
p_spudec
)
{
/* Re-align the buffer on an 8-bit boundary */
RealignBits
(
&
p_spudec
->
bit_stream
);
/* The total SPU packet size, often bigger than a PS packet */
p_spudec
->
i_spu_size
=
GetBits
(
&
p_spudec
->
bit_stream
,
16
);
/* The RLE stuff size (remove 4 because we just read 32 bits) */
p_spudec
->
i_rle_size
=
ShowBits
(
&
p_spudec
->
bit_stream
,
16
)
-
4
;
/* If the values we got are a bit strange, skip packet */
if
(
!
p_spudec
->
i_spu_size
||
(
p_spudec
->
i_rle_size
>=
p_spudec
->
i_spu_size
)
)
{
return
VLC_EGENERIC
;
}
RemoveBits
(
&
p_spudec
->
bit_stream
,
16
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* ParsePacket: parse an SPU packet and send it to the video output
*****************************************************************************
* This function parses the SPU packet and, if valid, sends it to the
* video output.
*****************************************************************************/
void
E_
(
ParsePacket
)(
spudec_thread_t
*
p_spudec
)
void
E_
(
ParsePacket
)(
decoder_t
*
p_dec
)
{
subpicture_t
*
p_spu
;
uint8_t
*
p_src
;
unsigned
int
i_offset
;
mtime_t
i_pts
;
msg_Dbg
(
p_spudec
->
p_fifo
,
"trying to gather a 0x%.2x long subtitle"
,
p_spudec
->
i_spu_size
);
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
/* We cannot display a subpicture with no date */
NextPTS
(
&
p_spudec
->
bit_stream
,
&
i_pts
,
NULL
);
if
(
i_pts
==
0
)
{
msg_Warn
(
p_spudec
->
p_fifo
,
"subtitle without a date"
);
return
;
}
subpicture_t
*
p_spu
;
/* Allocate the subpicture internal data. */
p_spu
=
vout_CreateSubPicture
(
p_spudec
->
p_vout
,
MEMORY_SUBPICTURE
);
p_spu
=
vout_CreateSubPicture
(
p_sys
->
p_vout
,
MEMORY_SUBPICTURE
);
if
(
p_spu
==
NULL
)
{
return
;
...
...
@@ -126,17 +85,10 @@ void E_(ParsePacket)( spudec_thread_t *p_spudec )
* expand the RLE stuff so that we won't need to read nibbles later
* on. This will speed things up a lot. Plus, we'll only need to do
* this stupid interlacing stuff once. */
p_spu
->
p_sys
=
malloc
(
sizeof
(
subpicture_sys_t
)
+
p_spudec
->
i_rle_size
*
4
);
if
(
p_spu
->
p_sys
==
NULL
)
{
vout_DestroySubPicture
(
p_spudec
->
p_vout
,
p_spu
);
return
;
}
p_spu
->
p_sys
=
malloc
(
sizeof
(
subpicture_sys_t
)
+
4
*
p_sys
->
i_rle_size
);
/* Fill the p_spu structure */
vlc_mutex_init
(
p_
spudec
->
p_fifo
,
&
p_spu
->
p_sys
->
lock
);
vlc_mutex_init
(
p_
dec
,
&
p_spu
->
p_sys
->
lock
);
p_spu
->
pf_render
=
E_
(
RenderSPU
);
p_spu
->
pf_destroy
=
DestroySPU
;
...
...
@@ -151,10 +103,10 @@ void E_(ParsePacket)( spudec_thread_t *p_spudec )
p_spu
->
p_sys
->
b_crop
=
VLC_FALSE
;
/* Get display time now. If we do it later, we may miss the PTS. */
p_spu
->
p_sys
->
i_pts
=
i_pts
;
p_spu
->
p_sys
->
i_pts
=
p_sys
->
i_pts
;
/* Attach to our input thread */
p_spu
->
p_sys
->
p_input
=
vlc_object_find
(
p_
spudec
->
p_fifo
,
p_spu
->
p_sys
->
p_input
=
vlc_object_find
(
p_
dec
,
VLC_OBJECT_INPUT
,
FIND_PARENT
);
if
(
p_spu
->
p_sys
->
p_input
)
{
...
...
@@ -173,70 +125,30 @@ void E_(ParsePacket)( spudec_thread_t *p_spudec )
}
}
/* Allocate the temporary buffer we will parse */
p_src
=
malloc
(
p_spudec
->
i_rle_size
);
if
(
p_src
==
NULL
)
{
msg_Err
(
p_spudec
->
p_fifo
,
"out of memory"
);
vout_DestroySubPicture
(
p_spudec
->
p_vout
,
p_spu
);
return
;
}
/* Get RLE data */
for
(
i_offset
=
0
;
i_offset
<
p_spudec
->
i_rle_size
;
i_offset
+=
SPU_CHUNK_SIZE
)
{
GetChunk
(
&
p_spudec
->
bit_stream
,
p_src
+
i_offset
,
(
i_offset
+
SPU_CHUNK_SIZE
<
p_spudec
->
i_rle_size
)
?
SPU_CHUNK_SIZE
:
p_spudec
->
i_rle_size
-
i_offset
);
/* Abort subtitle parsing if we were requested to stop */
if
(
p_spudec
->
p_fifo
->
b_die
)
{
free
(
p_src
);
vout_DestroySubPicture
(
p_spudec
->
p_vout
,
p_spu
);
return
;
}
}
#if 0
/* Dump the subtitle info */
intf_WarnHexDump( 5, p_spu->p_sys->p_data, p_spudec->i_rle_size );
#endif
/* Getting the control part */
if
(
ParseControlSeq
(
p_
spu
dec
,
p_spu
)
)
if
(
ParseControlSeq
(
p_dec
,
p_spu
)
)
{
/* There was a parse error, delete the subpicture */
free
(
p_src
);
vout_DestroySubPicture
(
p_spudec
->
p_vout
,
p_spu
);
vout_DestroySubPicture
(
p_sys
->
p_vout
,
p_spu
);
return
;
}
/* At this point, no more GetBit() command is needed, so we have all
* the data we need to tell whether the subtitle is valid. Thus we
* try to display it and we ignore b_die. */
if
(
ParseRLE
(
p_spudec
,
p_spu
,
p_src
)
)
/* We try to display it */
if
(
ParseRLE
(
p_dec
,
p_spu
)
)
{
/* There was a parse error, delete the subpicture */
free
(
p_src
);
vout_DestroySubPicture
(
p_spudec
->
p_vout
,
p_spu
);
vout_DestroySubPicture
(
p_sys
->
p_vout
,
p_spu
);
return
;
}
msg_Dbg
(
p_
spudec
->
p_fifo
,
"total size: 0x%x, RLE offsets: 0x%x 0x%x"
,
p_s
pudec
->
i_spu_size
,
msg_Dbg
(
p_
dec
,
"total size: 0x%x, RLE offsets: 0x%x 0x%x"
,
p_s
ys
->
i_spu_size
,
p_spu
->
p_sys
->
pi_offset
[
0
],
p_spu
->
p_sys
->
pi_offset
[
1
]
);
/* SPU is finished - we can ask the video output to display it */
vout_DisplaySubPicture
(
p_s
pudec
->
p_vout
,
p_spu
);
vout_DisplaySubPicture
(
p_s
ys
->
p_vout
,
p_spu
);
/* TODO: do stuff! */
/* Clean up */
free
(
p_src
);
}
/*****************************************************************************
...
...
@@ -246,11 +158,12 @@ void E_(ParsePacket)( spudec_thread_t *p_spudec )
* information, coordinates, and so on. For more information on the
* subtitles format, see http://sam.zoy.org/doc/dvd/subtitles/index.html
*****************************************************************************/
static
int
ParseControlSeq
(
spudec_thread_t
*
p_spudec
,
subpicture_t
*
p_spu
)
static
int
ParseControlSeq
(
decoder_t
*
p_dec
,
subpicture_t
*
p_spu
)
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
/* Our current index in the SPU packet */
unsigned
int
i_index
=
p_s
pudec
->
i_rle_size
+
4
;
unsigned
int
i_index
=
p_s
ys
->
i_rle_size
+
4
;
/* The next start-of-control-sequence index and the previous one */
unsigned
int
i_next_seq
=
0
,
i_cur_seq
=
0
;
...
...
@@ -267,24 +180,34 @@ static int ParseControlSeq( spudec_thread_t *p_spudec,
do
{
if
(
(
int
)
i_index
>=
p_sys
->
i_spu_size
+
1
)
{
/* sanity
* XXX only on test by loop as p_sys->buffer is bigger than needed
* to avoid checking at each access
*/
break
;
}
/* If we just read a command sequence, read the next one;
* otherwise, go on with the commands of the current sequence. */
if
(
i_command
==
SPU_CMD_END
)
{
/* Get the control sequence date */
date
=
(
mtime_t
)
GetBits
(
&
p_spudec
->
bit_stream
,
16
)
*
11000
date
=
(
mtime_t
)
GetWBE
(
&
p_sys
->
buffer
[
i_index
]
)
*
11000
;
/* FIXME How to access i_rate
* p_spudec->bit_stream.p_pes->i_rate / DEFAULT_RATE;
*/
/* Next offset */
i_cur_seq
=
i_index
;
i_next_seq
=
Get
Bits
(
&
p_spudec
->
bit_stream
,
16
);
i_next_seq
=
Get
WBE
(
&
p_sys
->
buffer
[
i_index
+
2
]
);
/* Skip what we just read */
i_index
+=
4
;
}
i_command
=
GetBits
(
&
p_spudec
->
bit_stream
,
8
);
i_index
++
;
i_command
=
p_sys
->
buffer
[
i_index
++
];
switch
(
i_command
)
{
...
...
@@ -305,17 +228,23 @@ static int ParseControlSeq( spudec_thread_t *p_spudec,
case
SPU_CMD_SET_PALETTE
:
/* 03xxxx (palette) */
if
(
p_
spu
dec
->
p_fifo
->
p_demux_data
&&
*
(
int
*
)
p_
spu
dec
->
p_fifo
->
p_demux_data
==
0xBeeF
)
if
(
p_dec
->
p_fifo
->
p_demux_data
&&
*
(
int
*
)
p_dec
->
p_fifo
->
p_demux_data
==
0xBeeF
)
{
u
int32_t
i_color
;
u
nsigned
int
idx
[
4
]
;
p_spu
->
p_sys
->
b_palette
=
VLC_TRUE
;
idx
[
0
]
=
(
p_sys
->
buffer
[
i_index
+
0
]
>>
4
)
&
0x0f
;
idx
[
1
]
=
(
p_sys
->
buffer
[
i_index
+
0
])
&
0x0f
;
idx
[
2
]
=
(
p_sys
->
buffer
[
i_index
+
1
]
>>
4
)
&
0x0f
;
idx
[
3
]
=
(
p_sys
->
buffer
[
i_index
+
1
])
&
0x0f
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
i_color
=
((
uint32_t
*
)((
char
*
)
p_spudec
->
p_fifo
->
p_demux_data
+
sizeof
(
int
)))[
GetBits
(
&
p_spudec
->
bit_stream
,
4
)
];
uint32_t
i_color
;
i_color
=
((
uint32_t
*
)((
char
*
)
p_dec
->
p_fifo
->
p_demux_data
+
sizeof
(
int
)))[
idx
[
i
]
];
/* FIXME: this job should be done sooner */
p_spu
->
p_sys
->
pi_yuv
[
3
-
i
][
0
]
=
(
i_color
>>
16
)
&
0xff
;
...
...
@@ -323,19 +252,15 @@ static int ParseControlSeq( spudec_thread_t *p_spudec,
p_spu
->
p_sys
->
pi_yuv
[
3
-
i
][
2
]
=
(
i_color
>>
8
)
&
0xff
;
}
}
else
{
RemoveBits
(
&
p_spudec
->
bit_stream
,
16
);
}
i_index
+=
2
;
break
;
case
SPU_CMD_SET_ALPHACHANNEL
:
/* 04xxxx (alpha channel) */
pi_alpha
[
3
]
=
GetBits
(
&
p_spudec
->
bit_stream
,
4
)
;
pi_alpha
[
2
]
=
GetBits
(
&
p_spudec
->
bit_stream
,
4
)
;
pi_alpha
[
1
]
=
GetBits
(
&
p_spudec
->
bit_stream
,
4
)
;
pi_alpha
[
0
]
=
GetBits
(
&
p_spudec
->
bit_stream
,
4
)
;
pi_alpha
[
3
]
=
(
p_sys
->
buffer
[
i_index
+
0
]
>>
4
)
&
0x0f
;
pi_alpha
[
2
]
=
(
p_sys
->
buffer
[
i_index
+
0
])
&
0x0f
;
pi_alpha
[
1
]
=
(
p_sys
->
buffer
[
i_index
+
1
]
>>
4
)
&
0x0f
;
pi_alpha
[
0
]
=
(
p_sys
->
buffer
[
i_index
+
1
])
&
0x0f
;
/* Ignore blank alpha palette. Sometimes spurious blank
* alpha palettes are present - dunno why. */
...
...
@@ -348,31 +273,29 @@ static int ParseControlSeq( spudec_thread_t *p_spudec,
}
else
{
msg_Warn
(
p_
spudec
->
p_fifo
,
"ignoring blank alpha palette"
);
msg_Warn
(
p_
dec
,
"ignoring blank alpha palette"
);
}
i_index
+=
2
;
break
;
case
SPU_CMD_SET_COORDINATES
:
/* 05xxxyyyxxxyyy (coordinates) */
p_spu
->
i_x
=
GetBits
(
&
p_spudec
->
bit_stream
,
12
);
p_spu
->
i_width
=
GetBits
(
&
p_spudec
->
bit_stream
,
12
)
-
p_spu
->
i_x
+
1
;
p_spu
->
i_x
=
(
p_sys
->
buffer
[
i_index
+
0
]
<<
4
)
|
((
p_sys
->
buffer
[
i_index
+
1
]
>>
4
)
&
0x0f
);
p_spu
->
i_width
=
(((
p_sys
->
buffer
[
i_index
+
1
]
&
0x0f
)
<<
8
)
|
p_sys
->
buffer
[
i_index
+
2
])
-
p_spu
->
i_x
+
1
;
p_spu
->
i_y
=
GetBits
(
&
p_spudec
->
bit_stream
,
12
);
p_spu
->
i_height
=
GetBits
(
&
p_spudec
->
bit_stream
,
12
)
-
p_spu
->
i_y
+
1
;
p_spu
->
i_y
=
(
p_sys
->
buffer
[
i_index
+
3
]
<<
4
)
|
((
p_sys
->
buffer
[
i_index
+
4
]
>>
4
)
&
0x0f
);
p_spu
->
i_height
=
(((
p_sys
->
buffer
[
i_index
+
4
]
&
0x0f
)
<<
8
)
|
p_sys
->
buffer
[
i_index
+
5
])
-
p_spu
->
i_y
+
1
;
i_index
+=
6
;
break
;
case
SPU_CMD_SET_OFFSETS
:
/* 06xxxxyyyy (byte offsets) */
p_spu
->
p_sys
->
pi_offset
[
0
]
=
GetBits
(
&
p_spudec
->
bit_stream
,
16
)
-
4
;
p_spu
->
p_sys
->
pi_offset
[
1
]
=
GetBits
(
&
p_spudec
->
bit_stream
,
16
)
-
4
;
p_spu
->
p_sys
->
pi_offset
[
0
]
=
GetWBE
(
&
p_sys
->
buffer
[
i_index
+
0
])
-
4
;
p_spu
->
p_sys
->
pi_offset
[
1
]
=
GetWBE
(
&
p_sys
->
buffer
[
i_index
+
2
])
-
4
;
i_index
+=
4
;
break
;
...
...
@@ -380,13 +303,12 @@ static int ParseControlSeq( spudec_thread_t *p_spudec,
break
;
default:
/* xx (unknown command) */
msg_Err
(
p_spudec
->
p_fifo
,
"unknown command 0x%.2x"
,
i_command
);
msg_Err
(
p_dec
,
"unknown command 0x%.2x"
,
i_command
);
return
VLC_EGENERIC
;
}
/* We need to check for quit commands here */
if
(
p_
spudec
->
p_fifo
->
b_die
)
if
(
p_
dec
->
b_die
)
{
return
VLC_EGENERIC
;
}
...
...
@@ -396,55 +318,41 @@ static int ParseControlSeq( spudec_thread_t *p_spudec,
/* Check that the next sequence index matches the current one */
if
(
i_next_seq
!=
i_cur_seq
)
{
msg_Err
(
p_
spudec
->
p_fifo
,
"index mismatch (0x%.4x != 0x%.4x)"
,
msg_Err
(
p_
dec
,
"index mismatch (0x%.4x != 0x%.4x)"
,
i_next_seq
,
i_cur_seq
);
return
VLC_EGENERIC
;
}
if
(
i_index
>
p_spudec
->
i_spu_size
)
if
(
(
int
)
i_index
>
p_sys
->
i_spu_size
)
{
msg_Err
(
p_
spudec
->
p_fifo
,
"uh-oh, we went too far (0x%.4x > 0x%.4x)"
,
i_index
,
p_spudec
->
i_spu_size
);
msg_Err
(
p_
dec
,
"uh-oh, we went too far (0x%.4x > 0x%.4x)"
,
i_index
,
p_sys
->
i_spu_size
);
return
VLC_EGENERIC
;
}
if
(
!
p_spu
->
i_start
)
{
msg_Err
(
p_
spudec
->
p_fifo
,
"no `start display' command"
);
msg_Err
(
p_
dec
,
"no `start display' command"
);
}
if
(
p_spu
->
i_stop
<=
p_spu
->
i_start
&&
!
p_spu
->
b_ephemer
)
{
/* This subtitle will live for 5 seconds or until the next subtitle */
p_spu
->
i_stop
=
p_spu
->
i_start
+
(
mtime_t
)
500
*
11000
p_spu
->
i_stop
=
p_spu
->
i_start
+
(
mtime_t
)
500
*
11000
;
/* FIXME how to access i_rate ?
* p_spudec->bit_stream.p_pes->i_rate / DEFAULT_RATE;
*/
p_spu
->
b_ephemer
=
VLC_TRUE
;
}
/* Get rid of padding bytes */
switch
(
p_spudec
->
i_spu_size
-
i_index
)
if
(
p_sys
->
i_spu_size
>
(
int
)
i_index
+
1
)
{
/* Zero or one padding byte, quite usual */
case
1
:
RemoveBits
(
&
p_spudec
->
bit_stream
,
8
);
i_index
++
;
case
0
:
break
;
/* More than one padding byte - this is very strange, but
/* Zero or one padding byte, are quite usual
* More than one padding byte - this is very strange, but
* we can deal with it */
default:
msg_Warn
(
p_spudec
->
p_fifo
,
"%i padding bytes, we usually get 0 or 1 of them"
,
p_spudec
->
i_spu_size
-
i_index
);
while
(
i_index
<
p_spudec
->
i_spu_size
)
{
RemoveBits
(
&
p_spudec
->
bit_stream
,
8
);
i_index
++
;
}
break
;
msg_Warn
(
p_dec
,
"%i padding bytes, we usually get 0 or 1 of them"
,
p_sys
->
i_spu_size
-
i_index
);
}
/* Successfully parsed ! */
...
...
@@ -458,9 +366,11 @@ static int ParseControlSeq( spudec_thread_t *p_spudec,
* convenient structure for later decoding. For more information on the
* subtitles format, see http://sam.zoy.org/doc/dvd/subtitles/index.html
*****************************************************************************/
static
int
ParseRLE
(
spudec_thread_t
*
p_spudec
,
subpicture_t
*
p_spu
,
uint8_t
*
p_src
)
static
int
ParseRLE
(
decoder_t
*
p_dec
,
subpicture_t
*
p_spu
)
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
uint8_t
*
p_src
=
&
p_sys
->
buffer
[
4
];
unsigned
int
i_code
;
unsigned
int
i_width
=
p_spu
->
i_width
;
...
...
@@ -519,7 +429,7 @@ static int ParseRLE( spudec_thread_t *p_spudec,
else
{
/* We have a boo boo ! */
msg_Err
(
p_
spudec
->
p_fifo
,
"unknown RLE code "
msg_Err
(
p_
dec
,
"unknown RLE code "
"0x%.4x"
,
i_code
);
return
VLC_EGENERIC
;
}
...
...
@@ -530,7 +440,7 @@ static int ParseRLE( spudec_thread_t *p_spudec,
if
(
(
(
i_code
>>
2
)
+
i_x
+
i_y
*
i_width
)
>
i_height
*
i_width
)
{
msg_Err
(
p_
spudec
->
p_fifo
,
msg_Err
(
p_
dec
,
"out of bounds, %i at (%i,%i) is out of %ix%i"
,
i_code
>>
2
,
i_x
,
i_y
,
i_width
,
i_height
);
return
VLC_EGENERIC
;
...
...
@@ -580,7 +490,7 @@ static int ParseRLE( spudec_thread_t *p_spudec,
/* Check that we didn't go too far */
if
(
i_x
>
i_width
)
{
msg_Err
(
p_
spudec
->
p_fifo
,
"i_x overflowed, %i > %i"
,
msg_Err
(
p_
dec
,
"i_x overflowed, %i > %i"
,
i_x
,
i_width
);
return
VLC_EGENERIC
;
}
...
...
@@ -598,8 +508,8 @@ static int ParseRLE( spudec_thread_t *p_spudec,
/* We shouldn't get any padding bytes */
if
(
i_y
<
i_height
)
{
msg_Err
(
p_
spudec
->
p_fifo
,
"padding bytes found in RLE sequence"
);
msg_Err
(
p_
spudec
->
p_fifo
,
"send mail to <sam@zoy.org> if you "
msg_Err
(
p_
dec
,
"padding bytes found in RLE sequence"
);
msg_Err
(
p_
dec
,
"send mail to <sam@zoy.org> if you "
"want to help debugging this"
);
/* Skip them just in case */
...
...
@@ -612,7 +522,7 @@ static int ParseRLE( spudec_thread_t *p_spudec,
return
VLC_EGENERIC
;
}
msg_Dbg
(
p_
spudec
->
p_fifo
,
"valid subtitle, size: %ix%i, position: %i,%i"
,
msg_Dbg
(
p_
dec
,
"valid subtitle, size: %ix%i, position: %i,%i"
,
p_spu
->
i_width
,
p_spu
->
i_height
,
p_spu
->
i_x
,
p_spu
->
i_y
);
#if 0 /* cropping */
...
...
@@ -679,7 +589,7 @@ static int ParseRLE( spudec_thread_t *p_spudec,
p_spu
->
p_sys
->
pi_yuv
[
i_shade
][
2
]
=
0x80
;
}
msg_Dbg
(
p_
spudec
->
p_fifo
,
msg_Dbg
(
p_
dec
,
"using custom palette (border %i, inner %i, shade %i)"
,
i_border
,
i_inner
,
i_shade
);
}
...
...
modules/codec/spudec/render.c
View file @
82ca25cb
...
...
@@ -2,7 +2,7 @@
* render.c : SPU renderer
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: render.c,v 1.
6 2003/10/25 00:49:14 sam
Exp $
* $Id: render.c,v 1.
7 2003/11/22 19:55:47 fenrir
Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Rudolf Cornelissen <rag.cornelissen@inter.nl.net>
...
...
@@ -27,7 +27,6 @@
* Preamble
*****************************************************************************/
#include <stdlib.h>
/* malloc(), free() */
#include <string.h>
/* memcpy(), memset() */
#include <vlc/vlc.h>
#include <vlc/vout.h>
...
...
modules/codec/spudec/spudec.c
View file @
82ca25cb
...
...
@@ -2,9 +2,10 @@
* spudec.c : SPU decoder thread
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: spudec.c,v 1.2
7 2003/11/16 21:07:31 gbazin
Exp $
* $Id: spudec.c,v 1.2
8 2003/11/22 19:55:47 fenrir
Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Laurent Aimar <fenrir@via.ecp.fr>
*
* 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
...
...
@@ -25,169 +26,258 @@
* Preamble
*****************************************************************************/
#include <stdlib.h>
/* malloc(), free() */
#include <string.h>
/* memcpy(), memset() */
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/decoder.h>
#include <vlc/input.h>
#include "spudec.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
int
OpenDecoder
(
vlc_object_t
*
);
static
int
RunDecoder
(
decoder_fifo_t
*
);
static
int
InitThread
(
spudec_thread_t
*
);
static
void
EndThread
(
spudec_thread_t
*
);
static
vout_thread_t
*
FindVout
(
spudec_thread_t
*
);
/*****************************************************************************
* Module descriptor.
*****************************************************************************/
static
int
DecoderOpen
(
vlc_object_t
*
);
static
int
PacketizerOpen
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
vlc_module_begin
();
set_description
(
_
(
"DVD subtitles decoder"
)
);
set_capability
(
"decoder"
,
50
);
set_callbacks
(
OpenDecoder
,
NULL
);
set_callbacks
(
DecoderOpen
,
Close
);
add_submodule
();
set_description
(
_
(
"DVD subtitles packetizer"
)
);
set_capability
(
"decoder"
,
50
);
set_callbacks
(
PacketizerOpen
,
Close
);
vlc_module_end
();
/*****************************************************************************
* OpenDecoder: probe the decoder and return score
* Local prototypes
*****************************************************************************/
static
vout_thread_t
*
FindVout
(
decoder_t
*
);
static
block_t
*
Reassemble
(
decoder_t
*
,
block_t
**
);
static
void
Decode
(
decoder_t
*
,
block_t
**
);
static
block_t
*
Packetize
(
decoder_t
*
,
block_t
**
);
/*****************************************************************************
* DecoderOpen
*****************************************************************************
* Tries to launch a decoder and return score so that the interface is able
* to chose.
*****************************************************************************/
static
int
OpenDecoder
(
vlc_object_t
*
p_this
)
static
int
DecoderOpen
(
vlc_object_t
*
p_this
)
{
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
decoder_sys_t
*
p_sys
;
if
(
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
's'
,
'p'
,
'u'
,
' '
)
&&
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
's'
,
'p'
,
'u'
,
'b'
)
)
if
(
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
's'
,
'p'
,
'u'
,
' '
)
&&
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
's'
,
'p'
,
'u'
,
'b'
)
)
{
return
VLC_EGENERIC
;
}
p_dec
->
pf_run
=
RunDecoder
;
p_dec
->
p_sys
=
p_sys
=
malloc
(
sizeof
(
decoder_sys_t
)
);
p_sys
->
b_packetizer
=
VLC_FALSE
;
p_sys
->
i_spu_size
=
0
;
p_sys
->
i_spu
=
0
;
p_sys
->
p_block
=
NULL
;
p_sys
->
p_vout
=
NULL
;
es_format_Init
(
&
p_dec
->
fmt_out
,
SPU_ES
,
VLC_FOURCC
(
's'
,
'p'
,
'u'
,
' '
)
);
p_dec
->
pf_decode_sub
=
Decode
;
p_dec
->
pf_packetize
=
Packetize
;
return
VLC_SUCCESS
;
}
/*****************************************************************************
* RunDecoder: this function is called just after the thread is created
* PacketizerOpen
*****************************************************************************
* Tries to launch a decoder and return score so that the interface is able
* to chose.
*****************************************************************************/
static
int
RunDecoder
(
decoder_fifo_t
*
p_fifo
)
static
int
PacketizerOpen
(
vlc_object_t
*
p_this
)
{
spudec_thread_t
*
p_spudec
;
/* Allocate the memory needed to store the thread's structure */
p_spudec
=
(
spudec_thread_t
*
)
malloc
(
sizeof
(
spudec_thread_t
)
);
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
if
(
p_spudec
==
NULL
)
if
(
DecoderOpen
(
p_this
)
)
{
msg_Err
(
p_fifo
,
"out of memory"
);
DecoderError
(
p_fifo
);
return
(
-
1
);
return
VLC_EGENERIC
;
}
p_dec
->
p_sys
->
b_packetizer
=
VLC_TRUE
;
/*
* Initialize the thread properties
*/
p_spudec
->
p_vout
=
NULL
;
p_spudec
->
p_fifo
=
p_fifo
;
return
VLC_SUCCESS
;
}
/*
* Initialize thread and free configuration
*/
p_spudec
->
p_fifo
->
b_error
=
InitThread
(
p_spudec
);
/*****************************************************************************
* Close:
*****************************************************************************/
static
void
Close
(
vlc_object_t
*
p_this
)
{
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
/*
* Main loop - it is not executed if an error occured during
* initialization
*/
while
(
(
!
p_spudec
->
p_fifo
->
b_die
)
&&
(
!
p_spudec
->
p_fifo
->
b_error
)
)
if
(
!
p_sys
->
b_packetizer
)
{
if
(
E_
(
SyncPacket
)(
p_spudec
)
)
/* FIXME check if it's ok to not lock vout */
if
(
p_sys
->
p_vout
!=
NULL
&&
p_sys
->
p_vout
->
p_subpicture
!=
NULL
)
{
continue
;
}
subpicture_t
*
p_subpic
;
int
i_subpic
;
for
(
i_subpic
=
0
;
i_subpic
<
VOUT_MAX_SUBPICTURES
;
i_subpic
++
)
{
p_subpic
=
&
p_sys
->
p_vout
->
p_subpicture
[
i_subpic
];
/* Find/Wait for a video output */
p_spudec
->
p_vout
=
FindVout
(
p_spudec
);
if
(
p_spudec
->
p_vout
)
if
(
p_subpic
!=
NULL
&&
(
(
p_subpic
->
i_status
==
RESERVED_SUBPICTURE
)
||
(
p_subpic
->
i_status
==
READY_SUBPICTURE
)
)
)
{
E_
(
ParsePacket
)(
p_spudec
);
vlc_object_release
(
p_spudec
->
p_vout
);
vout_DestroySubPicture
(
p_sys
->
p_vout
,
p_subpic
);
}
}
}
}
if
(
p_sys
->
p_block
)
{
block_ChainRelease
(
p_sys
->
p_block
);
}
free
(
p_sys
);
}
/*****************************************************************************
* Decode:
*****************************************************************************/
static
void
Decode
(
decoder_t
*
p_dec
,
block_t
**
pp_block
)
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
block_t
*
p_spu
=
Reassemble
(
p_dec
,
pp_block
);
/*
* Error loop
*/
if
(
p_spudec
->
p_fifo
->
b_error
)
if
(
p_spu
)
{
DecoderError
(
p_spudec
->
p_fifo
);
p_sys
->
i_spu
=
block_ChainExtract
(
p_spu
,
p_sys
->
buffer
,
65536
);
p_sys
->
i_pts
=
p_spu
->
i_pts
;
block_ChainRelease
(
p_spu
);
/* End of thread */
EndThread
(
p_spudec
);
return
-
1
;
if
(
(
p_sys
->
p_vout
=
FindVout
(
p_dec
)
)
)
{
/* Parse and decode */
E_
(
ParsePacket
)(
p_dec
);
vlc_object_release
(
p_sys
->
p_vout
);
}
/* End of thread */
EndThread
(
p_spudec
);
return
0
;
/* reinit context */
p_sys
->
i_spu_size
=
0
;
p_sys
->
i_rle_size
=
0
;
p_sys
->
i_spu
=
0
;
p_sys
->
p_block
=
NULL
;
}
}
/* following functions are local */
/*****************************************************************************
* Packetize:
*****************************************************************************/
static
block_t
*
Packetize
(
decoder_t
*
p_dec
,
block_t
**
pp_block
)
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
block_t
*
p_spu
=
Reassemble
(
p_dec
,
pp_block
);
if
(
p_spu
)
{
/* reinit context */
p_sys
->
i_spu_size
=
0
;
p_sys
->
i_rle_size
=
0
;
p_sys
->
i_spu
=
0
;
p_sys
->
p_block
=
NULL
;
return
block_ChainGather
(
p_spu
);
}
return
NULL
;
}
/*****************************************************************************
* InitThread: initialize spu decoder thread
*****************************************************************************
* This function is called from RunThread and performs the second step of the
* initialization. It returns 0 on success. Note that the thread's flag are not
* modified inside this function.
* Reassemble:
*****************************************************************************/
static
int
InitThread
(
spudec_thread_t
*
p_spudec
)
static
block_t
*
Reassemble
(
decoder_t
*
p_dec
,
block_t
**
pp_block
)
{
int
i_ret
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
block_t
*
p_block
;
if
(
pp_block
==
NULL
||
*
pp_block
==
NULL
)
{
return
NULL
;
}
p_block
=
*
pp_block
;
*
pp_block
=
NULL
;
/* Call InitBitstream anyway so p_spudec->bit_stream is in a known
* state before calling CloseBitstream */
i_ret
=
InitBitstream
(
&
p_spudec
->
bit_stream
,
p_spudec
->
p_fifo
,
NULL
,
NULL
);
if
(
p_sys
->
i_spu_size
<=
0
&&
(
p_block
->
i_pts
<=
0
||
p_block
->
i_buffer
<
4
)
)
{
msg_Dbg
(
p_dec
,
"invalid starting packet (size < 4 or pts <=0)"
);
block_Release
(
p_block
);
return
NULL
;
}
/* Check for a video output */
p_s
pudec
->
p_vout
=
FindVout
(
p_spudec
)
;
block_ChainAppend
(
&
p_sys
->
p_block
,
p_block
);
p_s
ys
->
i_spu
+=
p_block
->
i_buffer
;
if
(
!
p_spudec
->
p_vout
)
if
(
p_sys
->
i_spu_size
<=
0
)
{
return
-
1
;
p_sys
->
i_spu_size
=
(
p_block
->
p_buffer
[
0
]
<<
8
)
|
p_block
->
p_buffer
[
1
];
p_sys
->
i_rle_size
=
(
(
p_block
->
p_buffer
[
2
]
<<
8
)
|
p_block
->
p_buffer
[
3
]
)
-
4
;
msg_Dbg
(
p_dec
,
"i_spu_size=%d i_rle=%d"
,
p_sys
->
i_spu_size
,
p_sys
->
i_rle_size
);
if
(
p_sys
->
i_spu_size
<=
0
||
p_sys
->
i_rle_size
>=
p_sys
->
i_spu_size
)
{
p_sys
->
i_spu_size
=
0
;
p_sys
->
i_rle_size
=
0
;
p_sys
->
i_spu
=
0
;
p_sys
->
p_block
=
NULL
;
block_Release
(
p_block
);
return
NULL
;
}
}
/* It was just a check */
vlc_object_release
(
p_spudec
->
p_vout
);
p_spudec
->
p_vout
=
NULL
;
if
(
p_sys
->
i_spu
>=
p_sys
->
i_spu_size
)
{
/* We have a complete sub */
block_t
*
p_ret
=
p_sys
->
p_block
;
return
i_ret
;
msg_Dbg
(
p_dec
,
"SPU packets size=%d should be %d"
,
p_sys
->
i_spu
,
p_sys
->
i_spu_size
);
return
p_ret
;
}
return
NULL
;
}
/* following functions are local */
/*****************************************************************************
* FindVout: Find a vout or wait for one to be created.
*****************************************************************************/
static
vout_thread_t
*
FindVout
(
spudec_thread_t
*
p_spu
dec
)
static
vout_thread_t
*
FindVout
(
decoder_t
*
p_
dec
)
{
vout_thread_t
*
p_vout
=
NULL
;
/* Find an available video output */
do
{
if
(
p_
spudec
->
p_fifo
->
b_die
||
p_spudec
->
p_fifo
->
b_error
)
if
(
p_
dec
->
b_die
||
p_dec
->
b_error
)
{
break
;
}
p_vout
=
vlc_object_find
(
p_spudec
->
p_fifo
,
VLC_OBJECT_VOUT
,
FIND_ANYWHERE
);
p_vout
=
vlc_object_find
(
p_dec
,
VLC_OBJECT_VOUT
,
FIND_ANYWHERE
);
if
(
p_vout
)
{
break
;
...
...
@@ -200,33 +290,3 @@ static vout_thread_t *FindVout( spudec_thread_t *p_spudec )
return
p_vout
;
}
/*****************************************************************************
* EndThread: thread destruction
*****************************************************************************
* This function is called when the thread ends after a sucessful
* initialization.
*****************************************************************************/
static
void
EndThread
(
spudec_thread_t
*
p_spudec
)
{
if
(
p_spudec
->
p_vout
!=
NULL
&&
p_spudec
->
p_vout
->
p_subpicture
!=
NULL
)
{
subpicture_t
*
p_subpic
;
int
i_subpic
;
for
(
i_subpic
=
0
;
i_subpic
<
VOUT_MAX_SUBPICTURES
;
i_subpic
++
)
{
p_subpic
=
&
p_spudec
->
p_vout
->
p_subpicture
[
i_subpic
];
if
(
p_subpic
!=
NULL
&&
(
(
p_subpic
->
i_status
==
RESERVED_SUBPICTURE
)
||
(
p_subpic
->
i_status
==
READY_SUBPICTURE
)
)
)
{
vout_DestroySubPicture
(
p_spudec
->
p_vout
,
p_subpic
);
}
}
}
CloseBitstream
(
&
p_spudec
->
bit_stream
);
free
(
p_spudec
);
}
modules/codec/spudec/spudec.h
View file @
82ca25cb
...
...
@@ -2,7 +2,7 @@
* spudec.h : sub picture unit decoder thread interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: spudec.h,v 1.
7 2003/07/22 20:49:10 hartman
Exp $
* $Id: spudec.h,v 1.
8 2003/11/22 19:55:47 fenrir
Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
...
...
@@ -21,7 +21,21 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
typedef
struct
spudec_thread_t
spudec_thread_t
;
struct
decoder_sys_t
{
int
b_packetizer
;
mtime_t
i_pts
;
int
i_spu_size
;
int
i_rle_size
;
int
i_spu
;
block_t
*
p_block
;
uint8_t
buffer
[
65536
+
20
];
/* we will never overflow more than 11 bytes if I'm right */
vout_thread_t
*
p_vout
;
};
struct
subpicture_sys_t
{
...
...
@@ -44,35 +58,6 @@ struct subpicture_sys_t
unsigned
int
i_x_start
,
i_y_start
,
i_x_end
,
i_y_end
;
};
/*****************************************************************************
* spudec_thread_t : sub picture unit decoder thread descriptor
*****************************************************************************/
struct
spudec_thread_t
{
/*
* Thread properties and locks
*/
vlc_thread_t
thread_id
;
/* id for thread functions */
/*
* Input properties
*/
decoder_fifo_t
*
p_fifo
;
/* stores the PES stream data */
/* The bit stream structure handles the PES stream at the bit level */
bit_stream_t
bit_stream
;
/*
* Output properties
*/
vout_thread_t
*
p_vout
;
/* needed to create the spu objects */
/*
* Private properties
*/
unsigned
int
i_spu_size
;
/* size of current SPU packet */
unsigned
int
i_rle_size
;
/* size of the RLE part */
};
/*****************************************************************************
* Amount of bytes we GetChunk() in one go
*****************************************************************************/
...
...
@@ -93,9 +78,7 @@ struct spudec_thread_t
/*****************************************************************************
* Prototypes
*****************************************************************************/
int
E_
(
SyncPacket
)
(
spudec_thread_t
*
);
void
E_
(
ParsePacket
)
(
spudec_thread_t
*
);
void
E_
(
ParsePacket
)(
decoder_t
*
);
void
E_
(
RenderSPU
)
(
vout_thread_t
*
,
picture_t
*
,
const
subpicture_t
*
);
void
E_
(
RenderSPU
)
(
vout_thread_t
*
,
picture_t
*
,
const
subpicture_t
*
);
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