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
06ef387d
Commit
06ef387d
authored
Sep 22, 2007
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support for decoding Speex from RTP - refs #1291
Patch by Williams Hawkins
parent
4112e0fd
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
219 additions
and
13 deletions
+219
-13
THANKS
THANKS
+1
-0
modules/codec/speex.c
modules/codec/speex.c
+218
-13
No files found.
THANKS
View file @
06ef387d
...
...
@@ -206,6 +206,7 @@ Wade Majors <guru at startrek.com> - BeOS icon integration, debugging and fixes
Wallace Wadge <wwadge at gmail.com> - multiple programs TS mux
Watanabe Go <go at dsl.gr.jp> - fix for non-ASCII filenames
Wei Mingzhi <whistler_wmz at users.sourceforge.net> - Simplied Chinese translation
William Hawkins - Speex RTP payload format
Xavier Maillard <zedek at fxgsproject.org> - audio converters
Xavier Marchesini <xav at alarue.net> - Win32 fixes
Xènia Albà Cantero <xenia_alba at hotmail.com> - Catalan translation
...
...
modules/codec/speex.c
View file @
06ef387d
...
...
@@ -58,6 +58,7 @@ struct decoder_sys_t
SpeexHeader
*
p_header
;
SpeexStereoState
stereo
;
void
*
p_state
;
unsigned
int
rtp_rate
;
/*
* Common properties
...
...
@@ -85,6 +86,7 @@ static int OpenPacketizer( vlc_object_t * );
static
void
CloseDecoder
(
vlc_object_t
*
);
static
void
*
DecodeBlock
(
decoder_t
*
,
block_t
**
);
static
aout_buffer_t
*
DecodeRtpSpeexPacket
(
decoder_t
*
,
block_t
**
);
static
int
ProcessHeaders
(
decoder_t
*
);
static
int
ProcessInitialHeader
(
decoder_t
*
,
ogg_packet
*
);
static
void
*
ProcessPacket
(
decoder_t
*
,
ogg_packet
*
,
block_t
**
);
...
...
@@ -128,7 +130,8 @@ static int OpenDecoder( vlc_object_t *p_this )
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
if
(
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
's'
,
'p'
,
'x'
,
' '
)
)
if
(
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
's'
,
'p'
,
'x'
,
' '
)
&&
p_dec
->
fmt_in
.
i_codec
!=
VLC_FOURCC
(
's'
,
'p'
,
'x'
,
'r'
)
)
{
return
VLC_EGENERIC
;
}
...
...
@@ -140,7 +143,9 @@ static int OpenDecoder( vlc_object_t *p_this )
msg_Err
(
p_dec
,
"out of memory"
);
return
VLC_EGENERIC
;
}
p_dec
->
p_sys
->
bits
.
buf_size
=
0
;
p_dec
->
p_sys
->
b_packetizer
=
VLC_FALSE
;
p_dec
->
p_sys
->
rtp_rate
=
p_dec
->
fmt_in
.
audio
.
i_rate
;
aout_DateSet
(
&
p_sys
->
end_date
,
0
);
...
...
@@ -148,9 +153,24 @@ static int OpenDecoder( vlc_object_t *p_this )
p_dec
->
fmt_out
.
i_cat
=
AUDIO_ES
;
p_dec
->
fmt_out
.
i_codec
=
AOUT_FMT_S16_NE
;
/* Set callbacks */
/*
Set callbacks
If the codec is spxr then this decoder is
being invoked on a Speex stream arriving via RTP.
A special decoder callback is used.
*/
if
(
p_dec
->
fmt_in
.
i_codec
==
VLC_FOURCC
(
's'
,
'p'
,
'x'
,
'r'
))
{
msg_Dbg
(
p_dec
,
"Using RTP version of Speex decoder @ rate %d."
,
p_dec
->
fmt_in
.
audio
.
i_rate
);
p_dec
->
pf_decode_audio
=
(
aout_buffer_t
*
(
*
)(
decoder_t
*
,
block_t
**
))
DecodeRtpSpeexPacket
;
}
else
{
p_dec
->
pf_decode_audio
=
(
aout_buffer_t
*
(
*
)(
decoder_t
*
,
block_t
**
))
DecodeBlock
;
}
p_dec
->
pf_packetize
=
(
block_t
*
(
*
)(
decoder_t
*
,
block_t
**
))
DecodeBlock
;
...
...
@@ -212,12 +232,10 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
/* Check for headers */
if
(
p_sys
->
i_headers
==
0
&&
p_dec
->
fmt_in
.
i_extra
)
{
/* Headers already available as extra data */
p_sys
->
i_headers
=
2
;
}
else
if
(
oggpacket
.
bytes
&&
p_sys
->
i_headers
<
2
)
{
/* Backup headers as extra data */
uint8_t
*
p_extra
;
p_dec
->
fmt_in
.
p_extra
=
...
...
@@ -434,9 +452,76 @@ static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
*
pp_block
=
NULL
;
/* To avoid being fed the same packet again */
if
(
p_sys
->
b_packetizer
)
{
if
(
p_sys
->
p_header
->
frames_per_packet
>
1
)
{
short
*
p_frame_holder
=
NULL
;
int
i_bits_before
=
0
,
i_bits_after
=
0
,
i_bytes_in_speex_frame
=
0
,
i_pcm_output_size
=
0
,
i_bits_in_speex_frame
=
0
;
block_t
*
p_new_block
=
NULL
;
i_pcm_output_size
=
p_sys
->
p_header
->
frame_size
;
p_frame_holder
=
(
short
*
)
malloc
(
sizeof
(
short
)
*
i_pcm_output_size
);
speex_bits_read_from
(
&
p_sys
->
bits
,
(
char
*
)
p_oggpacket
->
packet
,
p_oggpacket
->
bytes
);
i_bits_before
=
speex_bits_remaining
(
&
p_sys
->
bits
);
speex_decode_int
(
p_sys
->
p_state
,
&
p_sys
->
bits
,
p_frame_holder
);
i_bits_after
=
speex_bits_remaining
(
&
p_sys
->
bits
);
i_bits_in_speex_frame
=
i_bits_before
-
i_bits_after
;
i_bytes_in_speex_frame
=
(
i_bits_in_speex_frame
+
(
8
-
(
i_bits_in_speex_frame
%
8
))
)
/
8
;
p_new_block
=
block_New
(
p_dec
,
i_bytes_in_speex_frame
);
memset
(
p_new_block
->
p_buffer
,
0xff
,
i_bytes_in_speex_frame
);
/*
* Copy the first frame in this packet to a new packet.
*/
speex_bits_rewind
(
&
p_sys
->
bits
);
speex_bits_write
(
&
p_sys
->
bits
,
p_new_block
->
p_buffer
,
i_bytes_in_speex_frame
);
/*
* Move the remaining part of the original packet (subsequent
* frames, if there are any) into the beginning
* of the original packet so
* they are preserved following the realloc.
* Note: Any bits that
* remain in the initial packet
* are "filler" if they do not constitute
* an entire byte.
*/
if
(
i_bits_after
>
7
)
{
/* round-down since we rounded-up earlier (to include
* the speex terminator code.
*/
i_bytes_in_speex_frame
--
;
speex_bits_write
(
&
p_sys
->
bits
,
p_block
->
p_buffer
,
p_block
->
i_buffer
-
i_bytes_in_speex_frame
);
p_block
=
block_Realloc
(
p_block
,
0
,
p_block
->
i_buffer
-
i_bytes_in_speex_frame
);
*
pp_block
=
p_block
;
}
else
{
speex_bits_reset
(
&
p_sys
->
bits
);
}
free
(
p_frame_holder
);
return
SendPacket
(
p_dec
,
p_oggpacket
/*Not used*/
,
p_new_block
);
}
else
{
return
SendPacket
(
p_dec
,
p_oggpacket
,
p_block
);
}
}
else
{
aout_buffer_t
*
p_aout_buffer
;
...
...
@@ -451,6 +536,124 @@ static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
}
}
static
aout_buffer_t
*
DecodeRtpSpeexPacket
(
decoder_t
*
p_dec
,
block_t
**
pp_block
)
{
block_t
*
p_speex_bit_block
=
*
pp_block
;
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
aout_buffer_t
*
p_aout_buffer
;
int
i_decode_ret
;
unsigned
int
i_speex_frame_size
;
if
(
!
p_speex_bit_block
||
p_speex_bit_block
->
i_pts
==
0
)
return
NULL
;
/*
If the SpeexBits buffer size is 0 (a default value),
we know that a proper initialization has not yet been done.
*/
if
(
p_sys
->
bits
.
buf_size
==
0
)
{
p_sys
->
p_header
=
(
SpeexHeader
*
)
malloc
(
sizeof
(
SpeexHeader
));
if
(
!
p_sys
->
p_header
)
{
msg_Err
(
p_dec
,
"Could not allocate a Speex header."
);
return
NULL
;
}
speex_init_header
(
p_sys
->
p_header
,
p_sys
->
rtp_rate
,
1
,
&
speex_nb_mode
);
speex_bits_init
(
&
p_sys
->
bits
);
p_sys
->
p_state
=
speex_decoder_init
(
&
speex_nb_mode
);
if
(
!
p_sys
->
p_state
)
{
msg_Err
(
p_dec
,
"Could not allocate a Speex decoder."
);
free
(
p_sys
->
p_header
);
return
NULL
;
}
/*
Assume that variable bit rate is enabled. Also assume
that there is only one frame per packet.
*/
p_sys
->
p_header
->
vbr
=
1
;
p_sys
->
p_header
->
frames_per_packet
=
1
;
p_dec
->
fmt_out
.
audio
.
i_channels
=
p_sys
->
p_header
->
nb_channels
;
p_dec
->
fmt_out
.
audio
.
i_physical_channels
=
p_dec
->
fmt_out
.
audio
.
i_original_channels
=
pi_channels_maps
[
p_sys
->
p_header
->
nb_channels
];
p_dec
->
fmt_out
.
audio
.
i_rate
=
p_sys
->
p_header
->
rate
;
if
(
speex_mode_query
(
&
speex_nb_mode
,
SPEEX_MODE_FRAME_SIZE
,
&
i_speex_frame_size
)
)
{
msg_Err
(
p_dec
,
"Could not determine the frame size."
);
speex_decoder_destroy
(
p_sys
->
p_state
);
free
(
p_sys
->
p_header
);
return
NULL
;
}
p_dec
->
fmt_out
.
audio
.
i_bytes_per_frame
=
i_speex_frame_size
;
aout_DateInit
(
&
p_sys
->
end_date
,
p_sys
->
p_header
->
rate
);
}
/*
If the SpeexBits are initialized but there is
still no header, an error must be thrown.
*/
if
(
!
p_sys
->
p_header
)
{
msg_Err
(
p_dec
,
"There is no valid Speex header found."
);
return
NULL
;
}
*
pp_block
=
NULL
;
if
(
!
aout_DateGet
(
&
p_sys
->
end_date
)
)
aout_DateSet
(
&
p_sys
->
end_date
,
p_speex_bit_block
->
i_dts
);
/*
Ask for a new audio output buffer and make sure
we get one.
*/
p_aout_buffer
=
p_dec
->
pf_aout_buffer_new
(
p_dec
,
p_sys
->
p_header
->
frame_size
);
if
(
!
p_aout_buffer
||
p_aout_buffer
->
i_nb_bytes
==
0
)
{
msg_Err
(
p_dec
,
"Oops: No new buffer was returned!"
);
return
NULL
;
}
/*
Read the Speex payload into the SpeexBits buffer.
*/
speex_bits_read_from
(
&
p_sys
->
bits
,
(
char
*
)
p_speex_bit_block
->
p_buffer
,
p_speex_bit_block
->
i_buffer
);
/*
Decode the input and ensure that no errors
were encountered.
*/
i_decode_ret
=
speex_decode_int
(
p_sys
->
p_state
,
&
p_sys
->
bits
,
p_aout_buffer
->
p_buffer
);
if
(
i_decode_ret
<
0
)
{
msg_Err
(
p_dec
,
"Decoding failed. Perhaps we have a bad stream?"
);
return
NULL
;
}
/*
Handle date management on the audio output buffer.
*/
p_aout_buffer
->
start_date
=
aout_DateGet
(
&
p_sys
->
end_date
);
p_aout_buffer
->
end_date
=
aout_DateIncrement
(
&
p_sys
->
end_date
,
p_sys
->
p_header
->
frame_size
);
p_sys
->
i_frame_in_packet
++
;
block_Release
(
p_speex_bit_block
);
return
p_aout_buffer
;
}
/*****************************************************************************
* DecodePacket: decodes a Speex packet.
*****************************************************************************/
...
...
@@ -484,14 +687,14 @@ static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
(
int16_t
*
)
p_aout_buffer
->
p_buffer
)
)
{
case
-
2
:
msg_
Warn
(
p_dec
,
"decoding error: corrupted stream?"
);
msg_
Err
(
p_dec
,
"decoding error: corrupted stream?"
);
case
-
1
:
/* End of stream */
return
NULL
;
}
if
(
speex_bits_remaining
(
&
p_sys
->
bits
)
<
0
)
{
msg_
Warn
(
p_dec
,
"decoding overflow: corrupted stream?"
);
msg_
Err
(
p_dec
,
"decoding overflow: corrupted stream?"
);
}
if
(
p_sys
->
p_header
->
nb_channels
==
2
)
...
...
@@ -502,7 +705,7 @@ static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
/* Date management */
p_aout_buffer
->
start_date
=
aout_DateGet
(
&
p_sys
->
end_date
);
p_aout_buffer
->
end_date
=
aout_DateIncrement
(
&
p_sys
->
end_date
,
p_sys
->
p_header
->
frame_size
);
aout_DateIncrement
(
&
p_sys
->
end_date
,
p_sys
->
p_header
->
frame_size
);
p_sys
->
i_frame_in_packet
++
;
...
...
@@ -526,10 +729,12 @@ static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
p_block
->
i_dts
=
p_block
->
i_pts
=
aout_DateGet
(
&
p_sys
->
end_date
);
if
(
p_sys
->
i_headers
>=
p_sys
->
p_header
->
extra_headers
+
2
)
{
p_block
->
i_length
=
aout_DateIncrement
(
&
p_sys
->
end_date
,
p_sys
->
p_header
->
frame_size
)
-
p_block
->
i_pts
;
}
else
p_block
->
i_length
=
0
;
...
...
@@ -566,14 +771,14 @@ static void ParseSpeexComments( decoder_t *p_dec, ogg_packet *p_oggpacket )
if
(
p_oggpacket
->
bytes
<
8
)
{
msg_
Warn
(
p_dec
,
"invalid/corrupted comments"
);
msg_
Err
(
p_dec
,
"invalid/corrupted comments"
);
return
;
}
i_len
=
readint
(
p_buf
,
0
);
p_buf
+=
4
;
if
(
i_len
>
p_oggpacket
->
bytes
-
4
)
{
msg_
Warn
(
p_dec
,
"invalid/corrupted comments"
);
msg_
Err
(
p_dec
,
"invalid/corrupted comments"
);
return
;
}
...
...
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