Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
GSoC
GSoC2018
macOS
vlc
Commits
4764ebc9
Commit
4764ebc9
authored
Oct 28, 2002
by
Laurent Aimar
Browse files
* all : add audio decoding support in ffmpeg module, since they have
added wma1/2 decoder... :))
parent
ec8efba6
Changes
8
Hide whitespace changes
Inline
Side-by-side
modules/codec/ffmpeg/Modules.am
View file @
4764ebc9
SOURCES_ffmpeg = modules/codec/ffmpeg/ffmpeg.c
SOURCES_ffmpeg = modules/codec/ffmpeg/ffmpeg.c \
modules/codec/ffmpeg/video.c \
modules/codec/ffmpeg/audio.c
noinst_HEADERS += modules/codec/ffmpeg/ffmpeg.h
noinst_HEADERS += modules/codec/ffmpeg/ffmpeg.h \
modules/codec/ffmpeg/video.h \
modules/codec/ffmpeg/audio.h
modules/codec/ffmpeg/audio.c
0 → 100644
View file @
4764ebc9
/*****************************************************************************
* audio.c: audio decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: audio.c,v 1.1 2002/10/28 06:26:11 fenrir Exp $
*
* Authors: 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include
<stdlib.h>
/* malloc(), free() */
#include
<vlc/vlc.h>
#include
<vlc/vout.h>
#include
<vlc/aout.h>
#include
<vlc/decoder.h>
#include
<vlc/input.h>
#ifdef HAVE_UNISTD_H
#include
<unistd.h>
/* getpid() */
#endif
#include
<errno.h>
#include
<string.h>
#ifdef HAVE_SYS_TIMES_H
# include <sys/times.h>
#endif
#include
"avcodec.h"
/* ffmpeg */
#include
"postprocessing/postprocessing.h"
#include
"ffmpeg.h"
#include
"audio.h"
/*
* Local prototypes
*/
int
E_
(
InitThread_Audio
)
(
adec_thread_t
*
);
void
E_
(
EndThread_Audio
)
(
adec_thread_t
*
);
void
E_
(
DecodeThread_Audio
)
(
adec_thread_t
*
);
static
int
i_channels_maps
[
6
]
=
{
0
,
AOUT_CHAN_MONO
,
AOUT_CHAN_STEREO
,
AOUT_CHAN_3F
,
AOUT_CHAN_2F2R
,
AOUT_CHAN_3F2R
};
/*****************************************************************************
* locales Functions
*****************************************************************************/
static
void
ffmpeg_GetWaveFormatEx
(
waveformatex_t
*
p_wh
,
u8
*
p_data
)
{
p_wh
->
i_formattag
=
GetWLE
(
p_data
);
p_wh
->
i_channels
=
GetWLE
(
p_data
+
2
);
p_wh
->
i_samplespersec
=
GetDWLE
(
p_data
+
4
);
p_wh
->
i_avgbytespersec
=
GetDWLE
(
p_data
+
8
);
p_wh
->
i_blockalign
=
GetWLE
(
p_data
+
12
);
p_wh
->
i_bitspersample
=
GetWLE
(
p_data
+
14
);
p_wh
->
i_size
=
GetWLE
(
p_data
+
16
);
if
(
p_wh
->
i_size
)
{
p_wh
->
p_data
=
malloc
(
p_wh
->
i_size
);
memcpy
(
p_wh
->
p_data
,
p_data
+
18
,
p_wh
->
i_size
);
}
}
/*****************************************************************************
*
* Functions that initialize, decode and end the decoding process
*
* Functions exported for ffmpeg.c
* * E_( InitThread_Audio )
* * E_( DecodeThread_Audio )
* * E_( EndThread_Video_Audio )
*****************************************************************************/
/*****************************************************************************
* InitThread: initialize vdec output thread
*****************************************************************************
* This function is called from decoder_Run 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.
*
* ffmpeg codec will be open, some memory allocated.
*****************************************************************************/
int
E_
(
InitThread_Audio
)(
adec_thread_t
*
p_adec
)
{
if
(
p_adec
->
p_fifo
->
p_demux_data
)
{
ffmpeg_GetWaveFormatEx
(
&
p_adec
->
format
,
(
u8
*
)
p_adec
->
p_fifo
->
p_demux_data
);
}
else
{
msg_Warn
(
p_adec
->
p_fifo
,
"audio informations missing"
);
}
/* ***** Fill p_context with init values ***** */
p_adec
->
p_context
->
sample_rate
=
p_adec
->
format
.
i_samplespersec
;
p_adec
->
p_context
->
channels
=
p_adec
->
format
.
i_channels
;
p_adec
->
p_context
->
block_align
=
p_adec
->
format
.
i_blockalign
;
p_adec
->
p_context
->
bit_rate
=
p_adec
->
format
.
i_avgbytespersec
*
8
;
if
(
(
p_adec
->
p_context
->
extradata_size
=
p_adec
->
format
.
i_size
)
>
0
)
{
p_adec
->
p_context
->
extradata
=
malloc
(
p_adec
->
format
.
i_size
);
memcpy
(
p_adec
->
p_context
->
extradata
,
p_adec
->
format
.
p_data
,
p_adec
->
format
.
i_size
);
}
/* ***** Open the codec ***** */
if
(
avcodec_open
(
p_adec
->
p_context
,
p_adec
->
p_codec
)
<
0
)
{
msg_Err
(
p_adec
->
p_fifo
,
"cannot open codec (%s)"
,
p_adec
->
psz_namecodec
);
return
(
-
1
);
}
else
{
msg_Dbg
(
p_adec
->
p_fifo
,
"ffmpeg codec (%s) started"
,
p_adec
->
psz_namecodec
);
}
p_adec
->
p_output
=
malloc
(
AVCODEC_MAX_AUDIO_FRAME_SIZE
);
p_adec
->
output_format
.
i_format
=
AOUT_FMT_S16_NE
;
p_adec
->
output_format
.
i_rate
=
p_adec
->
format
.
i_samplespersec
;
p_adec
->
output_format
.
i_channels
=
p_adec
->
format
.
i_channels
;
p_adec
->
p_aout
=
NULL
;
p_adec
->
p_aout_input
=
NULL
;
return
(
0
);
}
/*****************************************************************************
* DecodeThread: Called for decode one frame
*****************************************************************************/
void
E_
(
DecodeThread_Audio
)(
adec_thread_t
*
p_adec
)
{
pes_packet_t
*
p_pes
;
aout_buffer_t
*
p_aout_buffer
;
int
i_samplesperchannel
;
int
i_output_size
;
int
i_frame_size
;
int
i_status
;
do
{
input_ExtractPES
(
p_adec
->
p_fifo
,
&
p_pes
);
if
(
!
p_pes
)
{
p_adec
->
p_fifo
->
b_error
=
1
;
return
;
}
p_adec
->
pts
=
p_pes
->
i_pts
;
i_frame_size
=
p_pes
->
i_pes_size
;
if
(
i_frame_size
>
0
)
{
if
(
p_adec
->
i_buffer
<
i_frame_size
+
16
)
{
FREE
(
p_adec
->
p_buffer
);
p_adec
->
p_buffer
=
malloc
(
i_frame_size
+
16
);
p_adec
->
i_buffer
=
i_frame_size
+
16
;
}
E_
(
GetPESData
)(
p_adec
->
p_buffer
,
p_adec
->
i_buffer
,
p_pes
);
}
input_DeletePES
(
p_adec
->
p_fifo
->
p_packets_mgt
,
p_pes
);
}
while
(
i_frame_size
<=
0
);
i_status
=
avcodec_decode_audio
(
p_adec
->
p_context
,
(
s16
*
)
p_adec
->
p_output
,
&
i_output_size
,
p_adec
->
p_buffer
,
i_frame_size
);
if
(
i_status
<
0
)
{
msg_Warn
(
p_adec
->
p_fifo
,
"cannot decode one frame (%d bytes)"
,
i_frame_size
);
return
;
}
if
(
i_output_size
<=
0
)
{
msg_Warn
(
p_adec
->
p_fifo
,
"decoded %d samples bytes"
,
i_output_size
);
}
if
(
p_adec
->
p_context
->
channels
<=
0
||
p_adec
->
p_context
->
channels
>
5
)
{
msg_Warn
(
p_adec
->
p_fifo
,
"invalid channels count"
,
p_adec
->
p_context
->
channels
);
}
/* **** Now we can output these samples **** */
i_samplesperchannel
=
i_output_size
/
2
/
p_adec
->
output_format
.
i_channels
;
/* **** First check if we have a valid output **** */
if
(
(
!
p_adec
->
p_aout_input
)
||
(
p_adec
->
output_format
.
i_channels
!=
p_adec
->
p_context
->
channels
)
)
{
if
(
p_adec
->
p_aout_input
)
{
/* **** Delete the old **** */
aout_DecDelete
(
p_adec
->
p_aout
,
p_adec
->
p_aout_input
);
}
/* **** Create a new audio output **** */
p_adec
->
output_format
.
i_channels
=
i_channels_maps
[
p_adec
->
p_context
->
channels
];
aout_DateInit
(
&
p_adec
->
date
,
p_adec
->
output_format
.
i_rate
);
p_adec
->
p_aout_input
=
aout_DecNew
(
p_adec
->
p_fifo
,
&
p_adec
->
p_aout
,
&
p_adec
->
output_format
);
}
if
(
!
p_adec
->
p_aout_input
)
{
msg_Err
(
p_adec
->
p_fifo
,
"cannot create aout"
);
return
;
}
if
(
p_adec
->
pts
!=
0
&&
p_adec
->
pts
!=
aout_DateGet
(
&
p_adec
->
date
)
)
{
aout_DateSet
(
&
p_adec
->
date
,
p_adec
->
pts
);
}
else
if
(
!
aout_DateGet
(
&
p_adec
->
date
)
)
{
return
;
}
p_aout_buffer
=
aout_DecNewBuffer
(
p_adec
->
p_aout
,
p_adec
->
p_aout_input
,
i_samplesperchannel
);
if
(
!
p_aout_buffer
)
{
msg_Err
(
p_adec
->
p_fifo
,
"cannot get aout buffer"
);
p_adec
->
p_fifo
->
b_error
=
1
;
return
;
}
p_aout_buffer
->
start_date
=
aout_DateGet
(
&
p_adec
->
date
);
p_aout_buffer
->
end_date
=
aout_DateIncrement
(
&
p_adec
->
date
,
i_samplesperchannel
);
memcpy
(
p_aout_buffer
->
p_buffer
,
p_adec
->
p_output
,
p_aout_buffer
->
i_nb_bytes
);
aout_DecPlay
(
p_adec
->
p_aout
,
p_adec
->
p_aout_input
,
p_aout_buffer
);
return
;
}
/*****************************************************************************
* EndThread: thread destruction
*****************************************************************************
* This function is called when the thread ends after a sucessful
* initialization.
*****************************************************************************/
void
E_
(
EndThread_Audio
)(
adec_thread_t
*
p_adec
)
{
FREE
(
p_adec
->
format
.
p_data
);
if
(
p_adec
->
p_aout_input
)
{
aout_DecDelete
(
p_adec
->
p_aout
,
p_adec
->
p_aout_input
);
}
}
modules/codec/ffmpeg/audio.h
0 → 100644
View file @
4764ebc9
/*****************************************************************************
* audio.h: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: audio.h,v 1.1 2002/10/28 06:26:11 fenrir Exp $
*
* Authors: 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/* for an audio stream */
typedef
struct
waveformatex_s
{
u16
i_formattag
;
u16
i_channels
;
u32
i_samplespersec
;
u32
i_avgbytespersec
;
u16
i_blockalign
;
u16
i_bitspersample
;
u16
i_size
;
/* the extra size in bytes */
u8
*
p_data
;
/* The extra data */
}
waveformatex_t
;
typedef
struct
adec_thread_s
{
DECODER_THREAD_COMMON
waveformatex_t
format
;
/*
* Output properties
*/
u8
*
p_output
;
aout_instance_t
*
p_aout
;
/* opaque */
aout_input_t
*
p_aout_input
;
/* opaque */
audio_sample_format_t
output_format
;
audio_date_t
date
;
}
adec_thread_t
;
/*
* Local prototypes
*/
int
E_
(
InitThread_Audio
)
(
adec_thread_t
*
);
void
E_
(
EndThread_Audio
)
(
adec_thread_t
*
);
void
E_
(
DecodeThread_Audio
)
(
adec_thread_t
*
);
modules/codec/ffmpeg/ffmpeg.c
View file @
4764ebc9
...
...
@@ -2,7 +2,7 @@
* ffmpeg.c: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: ffmpeg.c,v 1.1
1
2002/10/2
7 16:58:13 gbazin
Exp $
* $Id: ffmpeg.c,v 1.1
2
2002/10/2
8 06:26:11 fenrir
Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
...
...
@@ -28,6 +28,7 @@
#include
<vlc/vlc.h>
#include
<vlc/vout.h>
#include
<vlc/aout.h>
#include
<vlc/decoder.h>
#include
<vlc/input.h>
...
...
@@ -47,19 +48,23 @@
#include
"postprocessing/postprocessing.h"
#include
"ffmpeg.h"
#include
"video.h"
// video ffmpeg specific
#include
"audio.h"
// audio ffmpeg specific
/*
* Local prototypes
*/
static
int
OpenDecoder
(
vlc_object_t
*
);
static
int
RunDecoder
(
decoder_fifo_t
*
);
static
int
InitThread
(
videodec_thread_t
*
);
static
void
End
Thread
(
videode
c_thread_t
*
);
static
void
Decode
Thread
(
videode
c_thread_t
*
);
static
int
Init
Thread
(
generi
c_thread_t
*
);
static
void
End
Thread
(
generi
c_thread_t
*
);
static
int
b_ffmpeginit
=
0
;
static
int
ffmpeg_GetFfmpegCodec
(
vlc_fourcc_t
,
int
*
,
int
*
,
char
**
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
...
...
@@ -131,7 +136,7 @@ vlc_module_begin();
"force chrominance deringing"
,
"force chrominance deringing (override other settings)"
);
set_description
(
_
(
"ffmpeg video decoder((MS)MPEG4,SVQ1,H263)"
)
);
set_description
(
_
(
"ffmpeg
audio/
video decoder((MS)MPEG4,SVQ1,H263
,WMV,WMA
)"
)
);
set_capability
(
"decoder"
,
70
);
set_callbacks
(
OpenDecoder
,
NULL
);
vlc_module_end
();
...
...
@@ -146,7 +151,7 @@ static int OpenDecoder( vlc_object_t *p_this )
{
decoder_fifo_t
*
p_fifo
=
(
decoder_fifo_t
*
)
p_this
;
if
(
ffmpeg_GetFfmpegCodec
(
p_fifo
->
i_fourcc
,
NULL
,
NULL
)
)
if
(
ffmpeg_GetFfmpegCodec
(
p_fifo
->
i_fourcc
,
NULL
,
NULL
,
NULL
)
)
{
p_fifo
->
pf_run
=
RunDecoder
;
return
VLC_SUCCESS
;
...
...
@@ -155,41 +160,59 @@ static int OpenDecoder( vlc_object_t *p_this )
return
VLC_EGENERIC
;
}
typedef
union
decoder_thread_u
{
generic_thread_t
gen
;
adec_thread_t
audio
;
vdec_thread_t
video
;
}
decoder_thread_t
;
/*****************************************************************************
* RunDecoder: this function is called just after the thread is created
*****************************************************************************/
static
int
RunDecoder
(
decoder_fifo_t
*
p_fifo
)
{
videode
c_thread_t
*
p_
v
dec
;
generi
c_thread_t
*
p_dec
oder
;
int
b_error
;
if
(
!
(
p_
v
dec
=
(
videodec_thread_t
*
)
malloc
(
sizeof
(
vi
deode
c
_thread_t
))
)
)
if
(
!
(
p_dec
oder
=
malloc
(
sizeof
(
de
c
ode
r
_thread_t
)
)
)
)
{
msg_Err
(
p_fifo
,
"out of memory"
);
DecoderError
(
p_fifo
);
return
(
-
1
);
}
memset
(
p_
v
dec
,
0
,
sizeof
(
vi
deode
c
_thread_t
)
);
memset
(
p_dec
oder
,
0
,
sizeof
(
de
c
ode
r
_thread_t
)
);
p_
v
dec
->
p_fifo
=
p_fifo
;
p_dec
oder
->
p_fifo
=
p_fifo
;
if
(
InitThread
(
p_
v
dec
)
!=
0
)
if
(
InitThread
(
p_dec
oder
)
!=
0
)
{
msg_Err
(
p_fifo
,
"initialization failed"
);
DecoderError
(
p_fifo
);
return
(
-
1
);
}
while
(
(
!
p_
v
dec
->
p_fifo
->
b_die
)
&&
(
!
p_
v
dec
->
p_fifo
->
b_error
)
)
while
(
(
!
p_dec
oder
->
p_fifo
->
b_die
)
&&
(
!
p_dec
oder
->
p_fifo
->
b_error
)
)
{
DecodeThread
(
p_vdec
);
switch
(
p_decoder
->
i_cat
)
{
case
VIDEO_ES
:
E_
(
DecodeThread_Video
)(
(
vdec_thread_t
*
)
p_decoder
);
break
;
case
AUDIO_ES
:
E_
(
DecodeThread_Audio
)(
(
adec_thread_t
*
)
p_decoder
);
break
;
}
}
if
(
(
b_error
=
p_
v
dec
->
p_fifo
->
b_error
)
)
if
(
(
b_error
=
p_dec
oder
->
p_fifo
->
b_error
)
)
{
DecoderError
(
p_
v
dec
->
p_fifo
);
DecoderError
(
p_dec
oder
->
p_fifo
);
}
EndThread
(
p_
v
dec
);
EndThread
(
p_dec
oder
);
if
(
b_error
)
{
...
...
@@ -199,355 +222,6 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
return
(
0
);
}
/*****************************************************************************
* locales Functions
*****************************************************************************/
#define GetWLE( p ) \
( *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) )
#define GetDWLE( p ) \
( *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) + \
( *((u8*)(p)+2) << 16 ) + ( *((u8*)(p)+3) << 24 ) )
#define FREE( p ) if( p ) free( p ); p = NULL
static
void
ffmpeg_ParseBitMapInfoHeader
(
bitmapinfoheader_t
*
p_bh
,
u8
*
p_data
)
{
p_bh
->
i_size
=
GetDWLE
(
p_data
);
p_bh
->
i_width
=
GetDWLE
(
p_data
+
4
);
p_bh
->
i_height
=
GetDWLE
(
p_data
+
8
);
p_bh
->
i_planes
=
GetWLE
(
p_data
+
12
);
p_bh
->
i_bitcount
=
GetWLE
(
p_data
+
14
);
p_bh
->
i_compression
=
GetDWLE
(
p_data
+
16
);
p_bh
->
i_sizeimage
=
GetDWLE
(
p_data
+
20
);
p_bh
->
i_xpelspermeter
=
GetDWLE
(
p_data
+
24
);
p_bh
->
i_ypelspermeter
=
GetDWLE
(
p_data
+
28
);
p_bh
->
i_clrused
=
GetDWLE
(
p_data
+
32
);
p_bh
->
i_clrimportant
=
GetDWLE
(
p_data
+
36
);
if
(
p_bh
->
i_size
>
40
)
{
p_bh
->
i_data
=
p_bh
->
i_size
-
40
;
if
(
(
p_bh
->
p_data
=
malloc
(
p_bh
->
i_data
)
)
)
{
memcpy
(
p_bh
->
p_data
,
p_data
+
40
,
p_bh
->
i_data
);
}
else
{
p_bh
->
i_data
=
0
;
}
}
else
{
p_bh
->
i_data
=
0
;
p_bh
->
p_data
=
NULL
;
}
}
static
void
GetPESData
(
u8
*
p_buf
,
int
i_max
,
pes_packet_t
*
p_pes
)
{
int
i_copy
;
int
i_count
;
data_packet_t
*
p_data
;
i_count
=
0
;
p_data
=
p_pes
->
p_first
;
while
(
p_data
!=
NULL
&&
i_count
<
i_max
)
{
i_copy
=
__MIN
(
p_data
->
p_payload_end
-
p_data
->
p_payload_start
,
i_max
-
i_count
);
if
(
i_copy
>
0
)
{
memcpy
(
p_buf
,
p_data
->
p_payload_start
,
i_copy
);
}
p_data
=
p_data
->
p_next
;
i_count
+=
i_copy
;
p_buf
+=
i_copy
;
}
if
(
i_count
<
i_max
)
{
memset
(
p_buf
,
0
,
i_max
-
i_count
);
}
}
/* Check if we have a Vout with good parameters */
static
int
ffmpeg_CheckVout
(
vout_thread_t
*
p_vout
,
int
i_width
,
int
i_height
,
int
i_aspect
,
int
i_chroma
)
{
if
(
!
p_vout
)
{
return
(
0
);
}
if
(
!
i_chroma
)
{
/* we will try to make conversion */
i_chroma
=
VLC_FOURCC
(
'I'
,
'4'
,
'2'
,
'0'
);
}