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
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