Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
Commits
f5cd136f
Commit
f5cd136f
authored
Nov 04, 2011
by
Clément Bœsch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ffmpeg: add -map_channel option.
Based on an initial work by Baptiste Coudurier.
parent
682e0eaf
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
108 additions
and
19 deletions
+108
-19
Changelog
Changelog
+1
-0
ffmpeg.texi
doc/ffmpeg.texi
+38
-0
ffmpeg.c
ffmpeg.c
+0
-0
ffplay.c
ffplay.c
+1
-1
audioconvert.c
libswresample/audioconvert.c
+8
-3
audioconvert.h
libswresample/audioconvert.h
+4
-1
swresample.c
libswresample/swresample.c
+23
-9
swresample.h
libswresample/swresample.h
+2
-2
swresample_internal.h
libswresample/swresample_internal.h
+2
-0
swresample_test.c
libswresample/swresample_test.c
+5
-3
Makefile
tests/Makefile
+8
-0
fate2.mak
tests/fate2.mak
+12
-0
mapchan-6ch-extract-2
tests/ref/fate/mapchan-6ch-extract-2
+2
-0
mapchan-6ch-extract-2-downmix-mono
tests/ref/fate/mapchan-6ch-extract-2-downmix-mono
+1
-0
mapchan-silent-mono
tests/ref/fate/mapchan-silent-mono
+1
-0
No files found.
Changelog
View file @
f5cd136f
...
...
@@ -72,6 +72,7 @@ easier to use. The changes are:
- Prores encoder
- Video Decoder Acceleration (VDA) HWAccel module.
- replacement Indeo 3 decoder
- new ffmpeg option: -map_channel
version 0.8:
...
...
doc/ffmpeg.texi
View file @
f5cd136f
...
...
@@ -721,6 +721,44 @@ ffmpeg -i INPUT -map 0 -map -0:a:1 OUTPUT
Note that using this option disables the default mappings for this output file.
@item -map
_
channel [@var
{
input
_
file
_
id
}
.@var
{
stream
_
specifier
}
.@var
{
channel
_
id
}
|-1][:@var
{
output
_
file
_
id
}
.@var
{
stream
_
specifier
}
]
Map an audio channel from a given input to an output. If
@var
{
output
_
file
_
id
}
.@var
{
stream
_
specifier
}
are not set, the audio channel will
be mapped on all the audio streams.
Using "-1" instead of
@var
{
input
_
file
_
id
}
.@var
{
stream
_
specifier
}
.@var
{
channel
_
id
}
will map a muted
channel.
For example, assuming @var
{
INPUT
}
is a stereo audio file, you can switch the
two audio channels with the following command:
@example
ffmpeg -i INPUT -map
_
channel 0.0.1 -map
_
channel 0.0.0 OUTPUT
@end example
If you want to mute the first channel and keep the second:
@example
ffmpeg -i INPUT -map
_
channel -1 -map
_
channel 0.0.1 OUTPUT
@end example
The order of the "-map
_
channel" option specifies the order of the channels in
the output stream. The output channel layout is guessed from the number of
channels mapped (mono if one "-map
_
channel", stereo if two, etc.). Using "-ac"
in combination of "-map
_
channel" makes the channel gain levels to be updated if
channel layouts don't match (for instance two "-map
_
channel" options and "-ac
6").
You can also extract each channel of an @var
{
INPUT
}
to specific outputs; the
following command extract each channel of the audio stream (file 0, stream 0)
to the respective @var
{
OUTPUT
_
CH0
}
and @var
{
OUTPUT
_
CH1
}
:
@example
ffmpeg -i INPUT -map
_
channel 0.0.0 OUTPUT
_
CH0 -map
_
channel 0.0.1 OUTPUT
_
CH1
@end example
Note that "-map
_
channel" is currently limited to the scope of one input for
each output; you can't for example use it to pick multiple input audio files
and mix them into one single output.
@item -map
_
metadata[:@var
{
metadata
_
type
}
][:@var
{
index
}
] @var
{
infile
}
[:@var
{
metadata
_
type
}
][:@var
{
index
}
] (@emph
{
output,per-metadata
}
)
Set metadata information of the next output file from @var
{
infile
}
. Note that
those are file indices (zero-based), not filenames.
...
...
ffmpeg.c
View file @
f5cd136f
This diff is collapsed.
Click to expand it.
ffplay.c
View file @
f5cd136f
...
...
@@ -2077,7 +2077,7 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
swr_free
(
&
is
->
swr_ctx
);
is
->
swr_ctx
=
swr_alloc2
(
NULL
,
is
->
audio_tgt_channel_layout
,
is
->
audio_tgt_fmt
,
is
->
audio_tgt_freq
,
dec_channel_layout
,
dec
->
sample_fmt
,
dec
->
sample_rate
,
0
,
NULL
);
NULL
,
0
,
NULL
);
if
(
!
is
->
swr_ctx
||
swr_init
(
is
->
swr_ctx
)
<
0
)
{
fprintf
(
stderr
,
"Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!
\n
"
,
dec
->
sample_rate
,
...
...
libswresample/audioconvert.c
View file @
f5cd136f
...
...
@@ -35,11 +35,13 @@
struct
AVAudioConvert
{
int
channels
;
int
fmt_pair
;
const
int
*
ch_map
;
};
AVAudioConvert
*
swr_audio_convert_alloc
(
enum
AVSampleFormat
out_fmt
,
enum
AVSampleFormat
in_fmt
,
int
channels
,
int
flags
)
int
channels
,
const
int
*
ch_map
,
int
flags
)
{
AVAudioConvert
*
ctx
;
ctx
=
av_malloc
(
sizeof
(
AVAudioConvert
));
...
...
@@ -47,6 +49,7 @@ AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt,
return
NULL
;
ctx
->
channels
=
channels
;
ctx
->
fmt_pair
=
out_fmt
+
AV_SAMPLE_FMT_NB
*
in_fmt
;
ctx
->
ch_map
=
ch_map
;
return
ctx
;
}
...
...
@@ -58,15 +61,17 @@ void swr_audio_convert_free(AVAudioConvert **ctx)
int
swr_audio_convert
(
AVAudioConvert
*
ctx
,
AudioData
*
out
,
AudioData
*
in
,
int
len
)
{
int
ch
;
const
uint8_t
null_input
[
8
]
=
{
0
};
av_assert0
(
ctx
->
channels
==
out
->
ch_count
);
//FIXME optimize common cases
for
(
ch
=
0
;
ch
<
ctx
->
channels
;
ch
++
){
const
int
is
=
(
in
->
planar
?
1
:
in
->
ch_count
)
*
in
->
bps
;
const
int
ich
=
ctx
->
ch_map
?
ctx
->
ch_map
[
ch
]
:
ch
;
const
int
is
=
ich
<
0
?
0
:
(
in
->
planar
?
1
:
in
->
ch_count
)
*
in
->
bps
;
const
int
os
=
(
out
->
planar
?
1
:
out
->
ch_count
)
*
out
->
bps
;
const
uint8_t
*
pi
=
i
n
->
ch
[
ch
];
const
uint8_t
*
pi
=
i
ch
<
0
?
null_input
:
in
->
ch
[
i
ch
];
uint8_t
*
po
=
out
->
ch
[
ch
];
uint8_t
*
end
=
po
+
os
*
len
;
if
(
!
po
)
...
...
libswresample/audioconvert.h
View file @
f5cd136f
...
...
@@ -42,11 +42,14 @@ typedef struct AVAudioConvert AVAudioConvert;
* @param in_fmt Input sample format
* @param channels Number of channels
* @param flags See AV_CPU_FLAG_xx
* @param ch_map list of the channels id to pick from the source stream, NULL
* if all channels must be selected
* @return NULL on error
*/
AVAudioConvert
*
swr_audio_convert_alloc
(
enum
AVSampleFormat
out_fmt
,
enum
AVSampleFormat
in_fmt
,
int
channels
,
int
flags
);
int
channels
,
const
int
*
ch_map
,
int
flags
);
/**
* Free audio sample format converter context.
...
...
libswresample/swresample.c
View file @
f5cd136f
...
...
@@ -38,6 +38,7 @@
static
const
AVOption
options
[]
=
{
{
"ich"
,
"input channel count"
,
OFFSET
(
in
.
ch_count
),
AV_OPT_TYPE_INT
,
{.
dbl
=
2
},
1
,
SWR_CH_MAX
,
0
},
{
"och"
,
"output channel count"
,
OFFSET
(
out
.
ch_count
),
AV_OPT_TYPE_INT
,
{.
dbl
=
2
},
1
,
SWR_CH_MAX
,
0
},
{
"uch"
,
"used channel count"
,
OFFSET
(
used_ch_count
),
AV_OPT_TYPE_INT
,
{.
dbl
=
2
},
1
,
SWR_CH_MAX
,
0
},
{
"isr"
,
"input sample rate"
,
OFFSET
(
in_sample_rate
),
AV_OPT_TYPE_INT
,
{.
dbl
=
48000
},
1
,
INT_MAX
,
0
},
{
"osr"
,
"output sample rate"
,
OFFSET
(
out_sample_rate
),
AV_OPT_TYPE_INT
,
{.
dbl
=
48000
},
1
,
INT_MAX
,
0
},
//{"ip" , "input planar" , OFFSET( in.planar ), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1, 0},
...
...
@@ -76,7 +77,7 @@ SwrContext *swr_alloc(void){
SwrContext
*
swr_alloc2
(
struct
SwrContext
*
s
,
int64_t
out_ch_layout
,
enum
AVSampleFormat
out_sample_fmt
,
int
out_sample_rate
,
int64_t
in_ch_layout
,
enum
AVSampleFormat
in_sample_fmt
,
int
in_sample_rate
,
int
log_offset
,
void
*
log_ctx
){
const
int
*
channel_map
,
int
log_offset
,
void
*
log_ctx
){
if
(
!
s
)
s
=
swr_alloc
();
if
(
!
s
)
return
NULL
;
...
...
@@ -90,9 +91,11 @@ SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampl
av_set_int
(
s
,
"isf"
,
in_sample_fmt
);
av_set_int
(
s
,
"isr"
,
in_sample_rate
);
s
->
channel_map
=
channel_map
;
s
->
in
.
ch_count
=
av_get_channel_layout_nb_channels
(
s
->
in_ch_layout
);
s
->
out
.
ch_count
=
av_get_channel_layout_nb_channels
(
s
->
out_ch_layout
);
s
->
int_sample_fmt
=
AV_SAMPLE_FMT_S16
;
s
->
used_ch_count
=
s
->
in
.
ch_count
;
return
s
;
}
...
...
@@ -167,13 +170,16 @@ int swr_init(SwrContext *s){
return
-
1
;
}
if
(
s
->
in
.
ch_count
&&
s
->
in_ch_layout
&&
s
->
in
.
ch_count
!=
av_get_channel_layout_nb_channels
(
s
->
in_ch_layout
)){
av_log
(
s
,
AV_LOG_WARNING
,
"Input channel layout has a different number of channels than there actually is, ignoring layout
\n
"
);
if
(
!
s
->
used_ch_count
)
s
->
used_ch_count
=
s
->
in
.
ch_count
;
if
(
s
->
used_ch_count
&&
s
->
in_ch_layout
&&
s
->
used_ch_count
!=
av_get_channel_layout_nb_channels
(
s
->
in_ch_layout
)){
av_log
(
s
,
AV_LOG_WARNING
,
"Input channel layout has a different number of channels than the number of used channels, ignoring layout
\n
"
);
s
->
in_ch_layout
=
0
;
}
if
(
!
s
->
in_ch_layout
)
s
->
in_ch_layout
=
av_get_default_channel_layout
(
s
->
in
.
ch_count
);
s
->
in_ch_layout
=
av_get_default_channel_layout
(
s
->
used_
ch_count
);
if
(
!
s
->
out_ch_layout
)
s
->
out_ch_layout
=
av_get_default_channel_layout
(
s
->
out
.
ch_count
);
...
...
@@ -182,10 +188,13 @@ int swr_init(SwrContext *s){
#define RSC 1 //FIXME finetune
if
(
!
s
->
in
.
ch_count
)
s
->
in
.
ch_count
=
av_get_channel_layout_nb_channels
(
s
->
in_ch_layout
);
if
(
!
s
->
used_ch_count
)
s
->
used_ch_count
=
s
->
in
.
ch_count
;
if
(
!
s
->
out
.
ch_count
)
s
->
out
.
ch_count
=
av_get_channel_layout_nb_channels
(
s
->
out_ch_layout
);
av_assert0
(
s
->
in
.
ch_count
);
av_assert0
(
s
->
used_ch_count
);
av_assert0
(
s
->
out
.
ch_count
);
s
->
resample_first
=
RSC
*
s
->
out
.
ch_count
/
s
->
in
.
ch_count
-
RSC
<
s
->
out_sample_rate
/
(
float
)
s
->
in_sample_rate
-
1
.
0
;
...
...
@@ -193,22 +202,27 @@ av_assert0(s->out.ch_count);
s
->
int_bps
=
av_get_bits_per_sample_fmt
(
s
->
int_sample_fmt
)
/
8
;
s
->
out
.
bps
=
av_get_bits_per_sample_fmt
(
s
->
out_sample_fmt
)
/
8
;
if
(
!
s
->
resample
&&
!
s
->
rematrix
){
if
(
!
s
->
resample
&&
!
s
->
rematrix
&&
!
s
->
channel_map
){
s
->
full_convert
=
swr_audio_convert_alloc
(
s
->
out_sample_fmt
,
s
->
in_sample_fmt
,
s
->
in
.
ch_count
,
0
);
s
->
in_sample_fmt
,
s
->
in
.
ch_count
,
NULL
,
0
);
return
0
;
}
s
->
in_convert
=
swr_audio_convert_alloc
(
s
->
int_sample_fmt
,
s
->
in_sample_fmt
,
s
->
in
.
ch_count
,
0
);
s
->
in_sample_fmt
,
s
->
used_ch_count
,
s
->
channel_map
,
0
);
s
->
out_convert
=
swr_audio_convert_alloc
(
s
->
out_sample_fmt
,
s
->
int_sample_fmt
,
s
->
out
.
ch_count
,
0
);
s
->
int_sample_fmt
,
s
->
out
.
ch_count
,
NULL
,
0
);
s
->
postin
=
s
->
in
;
s
->
preout
=
s
->
out
;
s
->
midbuf
=
s
->
in
;
s
->
in_buffer
=
s
->
in
;
if
(
s
->
channel_map
){
s
->
postin
.
ch_count
=
s
->
midbuf
.
ch_count
=
s
->
in_buffer
.
ch_count
=
s
->
used_ch_count
;
}
if
(
!
s
->
resample_first
){
s
->
midbuf
.
ch_count
=
s
->
out
.
ch_count
;
s
->
in_buffer
.
ch_count
=
s
->
out
.
ch_count
;
...
...
@@ -325,7 +339,7 @@ int swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_coun
if
((
ret
=
realloc_audio
(
&
s
->
postin
,
in_count
))
<
0
)
return
ret
;
if
(
s
->
resample_first
){
av_assert0
(
s
->
midbuf
.
ch_count
==
s
->
in
.
ch_count
);
av_assert0
(
s
->
midbuf
.
ch_count
==
s
->
used_
ch_count
);
if
((
ret
=
realloc_audio
(
&
s
->
midbuf
,
out_count
))
<
0
)
return
ret
;
}
else
{
...
...
libswresample/swresample.h
View file @
f5cd136f
...
...
@@ -25,7 +25,7 @@
#include "libavutil/samplefmt.h"
#define LIBSWRESAMPLE_VERSION_MAJOR 0
#define LIBSWRESAMPLE_VERSION_MINOR
1
#define LIBSWRESAMPLE_VERSION_MINOR
2
#define LIBSWRESAMPLE_VERSION_MICRO 0
#define SWR_CH_MAX 16
...
...
@@ -57,7 +57,7 @@ int swr_init(struct SwrContext *s);
*/
struct
SwrContext
*
swr_alloc2
(
struct
SwrContext
*
s
,
int64_t
out_ch_layout
,
enum
AVSampleFormat
out_sample_fmt
,
int
out_sample_rate
,
int64_t
in_ch_layout
,
enum
AVSampleFormat
in_sample_fmt
,
int
in_sample_rate
,
int
log_offset
,
void
*
log_ctx
);
const
int
*
channel_map
,
int
log_offset
,
void
*
log_ctx
);
/**
* Free the given SwrContext.
...
...
libswresample/swresample_internal.h
View file @
f5cd136f
...
...
@@ -45,6 +45,8 @@ typedef struct SwrContext { //FIXME find unused fields
int
out_sample_rate
;
int
flags
;
float
slev
,
clev
,
rematrix_volume
;
const
int
*
channel_map
;
///< channel index (or -1 if muted channel) map
int
used_ch_count
;
///< number of used channels (mapped channel count if channel_map, otherwise in.ch_count)
//below are private
int
int_bps
;
...
...
libswresample/swresample_test.c
View file @
f5cd136f
...
...
@@ -131,9 +131,11 @@ int main(int argc, char **argv){
in_sample_rate
,
out_sample_rate
,
av_get_sample_fmt_name
(
in_sample_fmt
),
av_get_sample_fmt_name
(
out_sample_fmt
));
forw_ctx
=
swr_alloc2
(
forw_ctx
,
out_ch_layout
,
out_sample_fmt
+
planar_out
,
out_sample_rate
,
in_ch_layout
,
in_sample_fmt
+
planar_in
,
in_sample_rate
,
0
,
0
);
backw_ctx
=
swr_alloc2
(
backw_ctx
,
in_ch_layout
,
in_sample_fmt
,
in_sample_rate
,
out_ch_layout
,
out_sample_fmt
+
planar_out
,
out_sample_rate
,
0
,
0
);
in_ch_layout
,
in_sample_fmt
+
planar_in
,
in_sample_rate
,
NULL
,
0
,
0
);
backw_ctx
=
swr_alloc2
(
backw_ctx
,
in_ch_layout
,
in_sample_fmt
,
in_sample_rate
,
out_ch_layout
,
out_sample_fmt
+
planar_out
,
out_sample_rate
,
NULL
,
0
,
0
);
if
(
swr_init
(
forw_ctx
)
<
0
)
fprintf
(
stderr
,
"swr_init(->) failed
\n
"
);
if
(
swr_init
(
backw_ctx
)
<
0
)
...
...
tests/Makefile
View file @
f5cd136f
...
...
@@ -30,6 +30,14 @@ tests/data/asynth-16000-1.sw: tests/audiogen$(HOSTEXESUF)
@
mkdir
-p
tests/data
$(M)
./
$<
$@
16000 1
tests/data/mapchan-6ch.sw
:
tests/audiogen$(HOSTEXESUF)
@
mkdir
-p
tests/data
$(M)
./
$<
$@
22050 6
tests/data/mapchan-mono.sw
:
tests/audiogen$(HOSTEXESUF)
@
mkdir
-p
tests/data
$(M)
./
$<
$@
22050 1
tests/data/asynth%.sw tests/vsynth%/00.pgm
:
TAG = GEN
include
$(SRC_PATH)/tests/fate.mak
...
...
tests/fate2.mak
View file @
f5cd136f
...
...
@@ -137,6 +137,18 @@ FATE_TESTS += fate-g722enc
fate-g722enc: tests/data/asynth-16000-1.sw
fate-g722enc: CMD = md5 -ar 16000 -ac 1 -f s16le -i $(TARGET_PATH)/tests/data/asynth-16000-1.sw -acodec g722 -ac 1 -f g722
FATE_TESTS += fate-mapchan-6ch-extract-2
fate-mapchan-6ch-extract-2: tests/data/mapchan-6ch.sw
fate-mapchan-6ch-extract-2: CMD = avconv -ar 22050 -ac 6 -i $(TARGET_PATH)/tests/data/mapchan-6ch.sw -map_channel 0.0.0 -f wav md5: -map_channel 0.0.1 -f wav md5:
FATE_TESTS += fate-mapchan-6ch-extract-2-downmix-mono
fate-mapchan-6ch-extract-2-downmix-mono: tests/data/mapchan-6ch.sw
fate-mapchan-6ch-extract-2-downmix-mono: CMD = md5 -ar 22050 -ac 6 -i $(TARGET_PATH)/tests/data/mapchan-6ch.sw -map_channel 0.0.1 -map_channel 0.0.0 -ac 1 -f wav
FATE_TESTS += fate-mapchan-silent-mono
fate-mapchan-silent-mono: tests/data/mapchan-mono.sw
fate-mapchan-silent-mono: CMD = md5 -ar 22050 -ac 1 -i $(TARGET_PATH)/tests/data/mapchan-mono.sw -map_channel -1 -map_channel 0.0.0 -f wav
FATE_TESTS += fate-msmpeg4v1
fate-msmpeg4v1: CMD = framecrc -flags +bitexact -dct fastint -idct simple -i $(SAMPLES)/msmpeg4v1/mpg4.avi -an
...
...
tests/ref/fate/mapchan-6ch-extract-2
0 → 100644
View file @
f5cd136f
6f091fe8c0be88c75921731dc9f74314
5c2d162b9024329eb367295d37b8ca0a
tests/ref/fate/mapchan-6ch-extract-2-downmix-mono
0 → 100644
View file @
f5cd136f
959645ed73e6d08d8f1e947eac5d0b92
tests/ref/fate/mapchan-silent-mono
0 → 100644
View file @
f5cd136f
4f5148f08587a4b9794aa52aec7852ac
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