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
3fc985ff
Commit
3fc985ff
authored
Nov 28, 2008
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added support of BD LPCM (using fcc bpcm)
parent
136ba664
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
297 additions
and
138 deletions
+297
-138
modules/codec/lpcm.c
modules/codec/lpcm.c
+297
-138
No files found.
modules/codec/lpcm.c
View file @
3fc985ff
...
...
@@ -8,6 +8,7 @@
* Henri Fallon <henri@videolan.org>
* Christophe Massiot <massiot@via.ecp.fr>
* Gildas Bazin <gbazin@videolan.org>
* Lauren Aimar <fenrir _AT_ videolan _DOT_ org >
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -73,7 +74,8 @@ struct decoder_sys_t
audio_date_t
end_date
;
/* */
unsigned
int
i_header_size
;
unsigned
i_header_size
;
bool
b_dvd
;
};
/*
...
...
@@ -87,14 +89,34 @@ struct decoder_sys_t
* - unknown (1 bit)
* - number of channels - 1 (3 bits) 1 == 2 channels
* - start code (8 bits) == 0x80
*
* LPCM BD header :
* - unkown (16 bits)
* - number of channels (4 bits)
* - frequency (4 bits)
* - bits per sample (2 bits)
* - unknown (6 bits)
*/
#define LPCM_DVD_HEADER_LEN (6)
#define LPCM_BD_HEADER_LEN (4)
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
void
*
DecodeFrame
(
decoder_t
*
,
block_t
**
);
static
int
DvdHeader
(
unsigned
*
pi_rate
,
unsigned
*
pi_channels
,
unsigned
*
pi_original_channels
,
unsigned
*
pi_bits
,
const
uint8_t
*
p_header
);
static
void
DvdExtract
(
aout_buffer_t
*
,
block_t
*
,
unsigned
i_bits
);
static
int
BdHeader
(
unsigned
*
pi_rate
,
unsigned
*
pi_channels
,
unsigned
*
pi_original_channels
,
unsigned
*
pi_bits
,
const
uint8_t
*
p_header
);
static
void
BdExtract
(
aout_buffer_t
*
,
block_t
*
);
/*****************************************************************************
* OpenCommon:
...
...
@@ -103,11 +125,18 @@ static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
{
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
decoder_sys_t
*
p_sys
;
bool
b_dvd
;
switch
(
p_dec
->
fmt_in
.
i_codec
)
{
/* DVD LPCM */
case
VLC_FOURCC
(
'l'
,
'p'
,
'c'
,
'm'
):
case
VLC_FOURCC
(
'l'
,
'p'
,
'c'
,
'b'
):
b_dvd
=
true
;
break
;
/* BD LPCM */
case
VLC_FOURCC
(
'b'
,
'p'
,
'c'
,
'm'
):
b_dvd
=
false
;
break
;
default:
return
VLC_EGENERIC
;
...
...
@@ -119,15 +148,16 @@ static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
/* Misc init */
p_sys
->
b_packetizer
=
b_packetizer
;
p_sys
->
i_header_size
=
LPCM_DVD_HEADER_LEN
;
aout_DateSet
(
&
p_sys
->
end_date
,
0
);
p_sys
->
i_header_size
=
b_dvd
?
LPCM_DVD_HEADER_LEN
:
LPCM_BD_HEADER_LEN
;
p_sys
->
b_dvd
=
b_dvd
;
/* Set output properties */
p_dec
->
fmt_out
.
i_cat
=
AUDIO_ES
;
if
(
b_packetizer
)
{
p_dec
->
fmt_out
.
i_codec
=
VLC_FOURCC
(
'l
'
,
'p'
,
'c'
,
'm'
);
p_dec
->
fmt_out
.
i_codec
=
b_dvd
?
VLC_FOURCC
(
'l'
,
'p'
,
'c'
,
'm'
)
:
VLC_FOURCC
(
'b
'
,
'p'
,
'c'
,
'm'
);
}
else
{
...
...
@@ -136,6 +166,7 @@ static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
case
24
:
case
20
:
p_dec
->
fmt_out
.
i_codec
=
VLC_FOURCC
(
's'
,
'2'
,
'4'
,
'b'
);
p_dec
->
fmt_out
.
audio
.
i_bitspersample
=
24
;
break
;
default:
p_dec
->
fmt_out
.
i_codec
=
VLC_FOURCC
(
's'
,
'1'
,
'6'
,
'b'
);
...
...
@@ -170,9 +201,8 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
{
decoder_sys_t
*
p_sys
=
p_dec
->
p_sys
;
block_t
*
p_block
;
unsigned
int
i_rate
=
0
,
i_original_channels
=
0
,
i_channels
=
0
;
int
i_frame_length
,
i_bitspersample
;
uint8_t
i_header
;
unsigned
int
i_rate
=
0
,
i_original_channels
=
0
,
i_channels
=
0
,
i_bits
=
0
;
int
i_frame_length
;
if
(
!
pp_block
||
!*
pp_block
)
return
NULL
;
...
...
@@ -200,137 +230,276 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
return
NULL
;
}
i_header
=
p_block
->
p_buffer
[
4
];
switch
(
(
i_header
>>
4
)
&
0x3
)
int
i_ret
;
if
(
p_sys
->
b_dvd
)
i_ret
=
DvdHeader
(
&
i_rate
,
&
i_channels
,
&
i_original_channels
,
&
i_bits
,
p_block
->
p_buffer
);
else
i_ret
=
BdHeader
(
&
i_rate
,
&
i_channels
,
&
i_original_channels
,
&
i_bits
,
p_block
->
p_buffer
);
if
(
i_ret
)
{
msg_Warn
(
p_dec
,
"no frame sync"
);
block_Release
(
p_block
);
return
NULL
;
}
/* Set output properties */
if
(
p_dec
->
fmt_out
.
audio
.
i_rate
!=
i_rate
)
{
aout_DateInit
(
&
p_sys
->
end_date
,
i_rate
);
aout_DateSet
(
&
p_sys
->
end_date
,
p_block
->
i_pts
);
}
p_dec
->
fmt_out
.
audio
.
i_rate
=
i_rate
;
p_dec
->
fmt_out
.
audio
.
i_channels
=
i_channels
;
p_dec
->
fmt_out
.
audio
.
i_original_channels
=
i_original_channels
;
p_dec
->
fmt_out
.
audio
.
i_physical_channels
=
i_original_channels
&
AOUT_CHAN_PHYSMASK
;
i_frame_length
=
(
p_block
->
i_buffer
-
p_sys
->
i_header_size
)
/
i_channels
*
8
/
i_bits
;
if
(
p_sys
->
b_packetizer
)
{
p_block
->
i_pts
=
p_block
->
i_dts
=
aout_DateGet
(
&
p_sys
->
end_date
);
p_block
->
i_length
=
aout_DateIncrement
(
&
p_sys
->
end_date
,
i_frame_length
)
-
p_block
->
i_pts
;
/* Just pass on the incoming frame */
return
p_block
;
}
else
{
/* */
if
(
i_bits
==
16
)
{
p_dec
->
fmt_out
.
i_codec
=
VLC_FOURCC
(
's'
,
'1'
,
'6'
,
'b'
);
p_dec
->
fmt_out
.
audio
.
i_bitspersample
=
16
;
}
else
{
p_dec
->
fmt_out
.
i_codec
=
VLC_FOURCC
(
's'
,
'2'
,
'4'
,
'b'
);
p_dec
->
fmt_out
.
audio
.
i_bitspersample
=
24
;
}
/* */
aout_buffer_t
*
p_aout_buffer
;
p_aout_buffer
=
decoder_NewAudioBuffer
(
p_dec
,
i_frame_length
);
if
(
!
p_aout_buffer
)
return
NULL
;
p_aout_buffer
->
start_date
=
aout_DateGet
(
&
p_sys
->
end_date
);
p_aout_buffer
->
end_date
=
aout_DateIncrement
(
&
p_sys
->
end_date
,
i_frame_length
);
p_block
->
p_buffer
+=
p_sys
->
i_header_size
;
p_block
->
i_buffer
-=
p_sys
->
i_header_size
;
if
(
p_sys
->
b_dvd
)
DvdExtract
(
p_aout_buffer
,
p_block
,
i_bits
);
else
BdExtract
(
p_aout_buffer
,
p_block
);
block_Release
(
p_block
);
return
p_aout_buffer
;
}
}
/*****************************************************************************
* CloseCommon : lpcm decoder destruction
*****************************************************************************/
static
void
CloseCommon
(
vlc_object_t
*
p_this
)
{
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
free
(
p_dec
->
p_sys
);
}
/*****************************************************************************
*
*****************************************************************************/
static
int
DvdHeader
(
unsigned
*
pi_rate
,
unsigned
*
pi_channels
,
unsigned
*
pi_original_channels
,
unsigned
*
pi_bits
,
const
uint8_t
*
p_header
)
{
const
uint8_t
i_header
=
p_header
[
4
];
switch
(
(
i_header
>>
4
)
&
0x3
)
{
case
0
:
i_rate
=
48000
;
*
p
i_rate
=
48000
;
break
;
case
1
:
i_rate
=
96000
;
*
p
i_rate
=
96000
;
break
;
case
2
:
i_rate
=
44100
;
*
p
i_rate
=
44100
;
break
;
case
3
:
i_rate
=
32000
;
*
p
i_rate
=
32000
;
break
;
}
i_channels
=
(
i_header
&
0x7
)
;
switch
(
i_channels
)
*
pi_channels
=
(
i_header
&
0x7
)
+
1
;
switch
(
*
pi_channels
-
1
)
{
case
0
:
i_original_channels
=
AOUT_CHAN_CENTER
;
*
p
i_original_channels
=
AOUT_CHAN_CENTER
;
break
;
case
1
:
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
;
*
p
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
;
break
;
case
2
:
/* This is unsure. */
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_LFE
;
*
p
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_LFE
;
break
;
case
3
:
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
*
p
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
;
break
;
case
4
:
/* This is unsure. */
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
*
p
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
|
AOUT_CHAN_LFE
;
break
;
case
5
:
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
*
p
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_LFE
;
break
;
case
6
:
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
*
p
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_MIDDLELEFT
|
AOUT_CHAN_MIDDLERIGHT
;
break
;
case
7
:
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
*
p
i_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_MIDDLELEFT
|
AOUT_CHAN_MIDDLERIGHT
|
AOUT_CHAN_LFE
;
break
;
}
switch
(
(
i_header
>>
6
)
&
0x3
)
switch
(
(
i_header
>>
6
)
&
0x3
)
{
case
2
:
p_dec
->
fmt_out
.
i_codec
=
VLC_FOURCC
(
's'
,
'2'
,
'4'
,
'b'
);
p_dec
->
fmt_out
.
audio
.
i_bitspersample
=
24
;
i_bitspersample
=
24
;
*
pi_bits
=
24
;
break
;
case
1
:
p_dec
->
fmt_out
.
i_codec
=
VLC_FOURCC
(
's'
,
'2'
,
'4'
,
'b'
);
p_dec
->
fmt_out
.
audio
.
i_bitspersample
=
24
;
i_bitspersample
=
20
;
*
pi_bits
=
20
;
break
;
case
0
:
default:
p_dec
->
fmt_out
.
i_codec
=
VLC_FOURCC
(
's'
,
'1'
,
'6'
,
'b'
);
p_dec
->
fmt_out
.
audio
.
i_bitspersample
=
16
;
i_bitspersample
=
16
;
*
pi_bits
=
16
;
break
;
}
/* Check frame sync and drop it. */
if
(
p_block
->
p_buffer
[
5
]
!=
0x80
)
if
(
p_header
[
5
]
!=
0x80
)
return
-
1
;
return
0
;
}
static
int
BdHeader
(
unsigned
*
pi_rate
,
unsigned
*
pi_channels
,
unsigned
*
pi_original_channels
,
unsigned
*
pi_bits
,
const
uint8_t
*
p_header
)
{
const
uint32_t
h
=
GetDWBE
(
p_header
);
switch
(
(
h
&
0xf000
)
>>
12
)
{
msg_Warn
(
p_dec
,
"no frame sync"
);
block_Release
(
p_block
);
return
NULL
;
}
case
1
:
*
pi_channels
=
1
;
*
pi_original_channels
=
AOUT_CHAN_CENTER
;
break
;
case
3
:
*
pi_channels
=
2
;
*
pi_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
;
break
;
case
4
:
*
pi_channels
=
3
;
*
pi_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_CENTER
;
break
;
case
5
:
*
pi_channels
=
3
;
*
pi_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_REARCENTER
;
break
;
case
6
:
*
pi_channels
=
4
;
*
pi_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_REARCENTER
;
break
;
case
7
:
*
pi_channels
=
4
;
*
pi_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
;
break
;
case
8
:
*
pi_channels
=
5
;
*
pi_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
;
break
;
case
9
:
*
pi_channels
=
6
;
*
pi_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
|
AOUT_CHAN_LFE
;
break
;
case
10
:
*
pi_channels
=
7
;
*
pi_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
|
AOUT_CHAN_MIDDLELEFT
|
AOUT_CHAN_MIDDLERIGHT
;
break
;
case
11
:
*
pi_channels
=
8
;
*
pi_original_channels
=
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
|
AOUT_CHAN_MIDDLELEFT
|
AOUT_CHAN_MIDDLERIGHT
|
AOUT_CHAN_LFE
;
break
;
/* Set output properties */
if
(
p_dec
->
fmt_out
.
audio
.
i_rate
!=
i_rate
)
{
aout_DateInit
(
&
p_sys
->
end_date
,
i_rate
);
aout_DateSet
(
&
p_sys
->
end_date
,
p_block
->
i_pts
);
default:
return
-
1
;
}
p_dec
->
fmt_out
.
audio
.
i_rate
=
i_rate
;
p_dec
->
fmt_out
.
audio
.
i_channels
=
i_channels
+
1
;
p_dec
->
fmt_out
.
audio
.
i_original_channels
=
i_original_channels
;
p_dec
->
fmt_out
.
audio
.
i_physical_channels
=
i_original_channels
&
AOUT_CHAN_PHYSMASK
;
i_frame_length
=
(
p_block
->
i_buffer
-
p_sys
->
i_header_size
)
/
p_dec
->
fmt_out
.
audio
.
i_channels
*
8
/
i_bitspersample
;
if
(
p_sys
->
b_packetizer
)
switch
(
(
h
>>
6
)
&
0x03
)
{
p_dec
->
fmt_out
.
i_codec
=
VLC_FOURCC
(
'l'
,
'p'
,
'c'
,
'm'
);
p_block
->
i_pts
=
p_block
->
i_dts
=
aout_DateGet
(
&
p_sys
->
end_date
);
p_block
->
i_length
=
aout_DateIncrement
(
&
p_sys
->
end_date
,
i_frame_length
)
-
p_block
->
i_pts
;
/* Just pass on the incoming frame */
return
p_block
;
case
1
:
*
pi_bits
=
16
;
break
;
case
2
:
/* 20 bits but samples are stored on 24 bits */
case
3
:
/* 24 bits */
*
pi_bits
=
24
;
break
;
default:
return
-
1
;
}
else
switch
(
(
h
>>
8
)
&
0x0f
)
{
aout_buffer_t
*
p_aout_buffer
;
p_aout_buffer
=
decoder_NewAudioBuffer
(
p_dec
,
i_frame_length
);
if
(
p_aout_buffer
==
NULL
)
return
NULL
;
p_aout_buffer
->
start_date
=
aout_DateGet
(
&
p_sys
->
end_date
);
p_aout_buffer
->
end_date
=
aout_DateIncrement
(
&
p_sys
->
end_date
,
i_frame_length
);
case
1
:
*
pi_rate
=
48000
;
break
;
case
4
:
*
pi_rate
=
96000
;
break
;
case
5
:
*
pi_rate
=
192000
;
break
;
default:
return
-
1
;
}
return
0
;
}
p_block
->
p_buffer
+=
p_sys
->
i_header_size
;
p_block
->
i_buffer
-=
p_sys
->
i_header_size
;
static
void
DvdExtract
(
aout_buffer_t
*
p_aout_buffer
,
block_t
*
p_block
,
unsigned
i_bits
)
{
uint8_t
*
p_out
=
p_aout_buffer
->
p_buffer
;
/* 20/24 bits LPCM use special packing */
if
(
i_bitspersample
==
24
)
if
(
i_bits
==
24
)
{
uint8_t
*
p_out
=
p_aout_buffer
->
p_buffer
;
while
(
p_block
->
i_buffer
/
12
)
{
/* Sample 1 */
...
...
@@ -355,10 +524,8 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
p_out
+=
12
;
}
}
else
if
(
i_bitspersample
==
20
)
else
if
(
i_bits
==
20
)
{
uint8_t
*
p_out
=
p_aout_buffer
->
p_buffer
;
while
(
p_block
->
i_buffer
/
10
)
{
/* Sample 1 */
...
...
@@ -385,21 +552,13 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
}
else
{
memcpy
(
p_aout_buffer
->
p_buffer
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
}
block_Release
(
p_block
);
return
p_aout_buffer
;
assert
(
i_bits
==
16
);
memcpy
(
p_out
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
}
}
/*****************************************************************************
* CloseCommon : lpcm decoder destruction
*****************************************************************************/
static
void
CloseCommon
(
vlc_object_t
*
p_this
)
static
void
BdExtract
(
aout_buffer_t
*
p_aout_buffer
,
block_t
*
p_block
)
{
decoder_t
*
p_dec
=
(
decoder_t
*
)
p_this
;
free
(
p_dec
->
p_sys
);
memcpy
(
p_aout_buffer
->
p_buffer
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
}
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