History

ffmpeg: add -map_channel option.

Based on an initial work by Baptiste Coudurier.

Clément Bœsch committed 15 years ago

Commit f5cd1361 parent 682e0ea15 files · +228 −22Browse files

Showing the changes to libswresample (6 of 15 files). Show all

Unified · Split

6 files
  1. libswresample/audioconvert.c +8 −3
  2. libswresample/audioconvert.h +4 −1
  3. libswresample/swresample.c +23 −9
  4. libswresample/swresample.h +2 −2
  5. libswresample/swresample_internal.h +2 −0
  6. libswresample/swresample_test.c +5 −3
libswresample/audioconvert.c+8−3
@@ -35,11 +35,13 @@ · 34 unmodified lines
3535 struct AVAudioConvert {
3636 int channels;
3737 int fmt_pair;
38+ const int *ch_map;
3839 };
3940
4041 AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt,
4142 enum AVSampleFormat in_fmt,
42− int channels, int flags)
43+ int channels, const int *ch_map,
44+ int flags)
4345 {
4446 AVAudioConvert *ctx;
4547 ctx = av_malloc(sizeof(AVAudioConvert));
@@ -47,6 +49,7 @@ AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt, · 1 unmodified line
4749 return NULL;
4850 ctx->channels = channels;
4951 ctx->fmt_pair = out_fmt + AV_SAMPLE_FMT_NB*in_fmt;
52+ ctx->ch_map = ch_map;
5053 return ctx;
5154 }
5255
@@ -58,15 +61,17 @@ void swr_audio_convert_free(AVAudioConvert **ctx) · 5 unmodified lines
5861 int swr_audio_convert(AVAudioConvert *ctx, AudioData *out, AudioData*in, int len)
5962 {
6063 int ch;
64+ const uint8_t null_input[8] = {0};
6165
6266 av_assert0(ctx->channels == out->ch_count);
6367
6468 //FIXME optimize common cases
6569
6670 for(ch=0; ch<ctx->channels; ch++){
67− const int is= (in ->planar ? 1 : in->ch_count) * in->bps;
71+ const int ich= ctx->ch_map ? ctx->ch_map[ch] : ch;
72+ const int is= ich < 0 ? 0 : (in->planar ? 1 : in->ch_count) * in->bps;
6873 const int os= (out->planar ? 1 :out->ch_count) *out->bps;
69− const uint8_t *pi= in ->ch[ch];
74+ const uint8_t *pi= ich < 0 ? null_input : in->ch[ich];
7075 uint8_t *po= out->ch[ch];
7176 uint8_t *end= po + os*len;
7277 if(!po)
libswresample/audioconvert.h+4−1
@@ -42,11 +42,14 @@ typedef struct AVAudioConvert AVAudioConvert; · 41 unmodified lines
4242 * @param in_fmt Input sample format
4343 * @param channels Number of channels
4444 * @param flags See AV_CPU_FLAG_xx
45+ * @param ch_map list of the channels id to pick from the source stream, NULL
46+ * if all channels must be selected
4547 * @return NULL on error
4648 */
4749 AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt,
4850 enum AVSampleFormat in_fmt,
49− int channels, int flags);
51+ int channels, const int *ch_map,
52+ int flags);
5053
5154 /**
5255 * Free audio sample format converter context.
libswresample/swresample.c+23−9
@@ -38,6 +38,7 @@ · 37 unmodified lines
3838 static const AVOption options[]={
3939 {"ich", "input channel count", OFFSET( in.ch_count ), AV_OPT_TYPE_INT, {.dbl=2}, 1, SWR_CH_MAX, 0},
4040 {"och", "output channel count", OFFSET(out.ch_count ), AV_OPT_TYPE_INT, {.dbl=2}, 1, SWR_CH_MAX, 0},
41+{"uch", "used channel count", OFFSET(used_ch_count ), AV_OPT_TYPE_INT, {.dbl=2}, 1, SWR_CH_MAX, 0},
4142 {"isr", "input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT, {.dbl=48000}, 1, INT_MAX, 0},
4243 {"osr", "output sample rate" , OFFSET(out_sample_rate), AV_OPT_TYPE_INT, {.dbl=48000}, 1, INT_MAX, 0},
4344 //{"ip" , "input planar" , OFFSET( in.planar ), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1, 0},
@@ -76,7 +77,7 @@ SwrContext *swr_alloc(void){ · 32 unmodified lines
7677
7778 SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
7879 int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,
79− int log_offset, void *log_ctx){
80+ const int *channel_map, int log_offset, void *log_ctx){
8081 if(!s) s= swr_alloc();
8182 if(!s) return NULL;
8283
@@ -90,9 +91,11 @@ SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampl · 7 unmodified lines
9091 av_set_int(s, "isf", in_sample_fmt);
9192 av_set_int(s, "isr", in_sample_rate);
9293
94+ s->channel_map = channel_map;
9395 s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
9496 s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);
9597 s->int_sample_fmt = AV_SAMPLE_FMT_S16;
98+ s->used_ch_count= s-> in.ch_count;
9699
97100 return s;
98101 }
@@ -167,13 +170,16 @@ int swr_init(SwrContext *s){ · 68 unmodified lines
167170 return -1;
168171 }
169172
170− if(s-> in.ch_count && s-> in_ch_layout && s->in.ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){
171− av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than there actually is, ignoring layout\n");
173+ if(!s->used_ch_count)
174+ s->used_ch_count= s->in.ch_count;
175+
176+ if(s->used_ch_count && s-> in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){
177+ av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n");
172178 s-> in_ch_layout= 0;
173179 }
174180
175181 if(!s-> in_ch_layout)
176− s-> in_ch_layout= av_get_default_channel_layout(s->in.ch_count);
182+ s-> in_ch_layout= av_get_default_channel_layout(s->used_ch_count);
177183 if(!s->out_ch_layout)
178184 s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count);
179185
@@ -182,10 +188,13 @@ int swr_init(SwrContext *s){ · 2 unmodified lines
182188 #define RSC 1 //FIXME finetune
183189 if(!s-> in.ch_count)
184190 s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
191+ if(!s->used_ch_count)
192+ s->used_ch_count= s->in.ch_count;
185193 if(!s->out.ch_count)
186194 s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);
187195
188196 av_assert0(s-> in.ch_count);
197+av_assert0(s->used_ch_count);
189198 av_assert0(s->out.ch_count);
190199 s->resample_first= RSC*s->out.ch_count/s->in.ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0;
191200
@@ -193,22 +202,27 @@ av_assert0(s->out.ch_count); · 1 unmodified line
193202 s->int_bps= av_get_bits_per_sample_fmt(s->int_sample_fmt)/8;
194203 s->out.bps= av_get_bits_per_sample_fmt(s->out_sample_fmt)/8;
195204
196− if(!s->resample && !s->rematrix){
205+ if(!s->resample && !s->rematrix && !s->channel_map){
197206 s->full_convert = swr_audio_convert_alloc(s->out_sample_fmt,
198− s-> in_sample_fmt, s-> in.ch_count, 0);
207+ s-> in_sample_fmt, s-> in.ch_count, NULL, 0);
199208 return 0;
200209 }
201210
202211 s->in_convert = swr_audio_convert_alloc(s->int_sample_fmt,
203− s-> in_sample_fmt, s-> in.ch_count, 0);
212+ s-> in_sample_fmt, s->used_ch_count, s->channel_map, 0);
204213 s->out_convert= swr_audio_convert_alloc(s->out_sample_fmt,
205− s->int_sample_fmt, s->out.ch_count, 0);
214+ s->int_sample_fmt, s->out.ch_count, NULL, 0);
206215
207216
208217 s->postin= s->in;
209218 s->preout= s->out;
210219 s->midbuf= s->in;
211220 s->in_buffer= s->in;
221+ if(s->channel_map){
222+ s->postin.ch_count=
223+ s->midbuf.ch_count=
224+ s->in_buffer.ch_count= s->used_ch_count;
225+ }
212226 if(!s->resample_first){
213227 s->midbuf.ch_count= s->out.ch_count;
214228 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 · 110 unmodified lines
325339 if((ret=realloc_audio(&s->postin, in_count))<0)
326340 return ret;
327341 if(s->resample_first){
328− av_assert0(s->midbuf.ch_count == s-> in.ch_count);
342+ av_assert0(s->midbuf.ch_count == s->used_ch_count);
329343 if((ret=realloc_audio(&s->midbuf, out_count))<0)
330344 return ret;
331345 }else{
libswresample/swresample.h+2−2
@@ -25,7 +25,7 @@ · 24 unmodified lines
2525 #include "libavutil/samplefmt.h"
2626
2727 #define LIBSWRESAMPLE_VERSION_MAJOR 0
28−#define LIBSWRESAMPLE_VERSION_MINOR 1
28+#define LIBSWRESAMPLE_VERSION_MINOR 2
2929 #define LIBSWRESAMPLE_VERSION_MICRO 0
3030
3131 #define SWR_CH_MAX 16
@@ -57,7 +57,7 @@ int swr_init(struct SwrContext *s); · 25 unmodified lines
5757 */
5858 struct SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
5959 int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,
60− int log_offset, void *log_ctx);
60+ const int *channel_map, int log_offset, void *log_ctx);
6161
6262 /**
6363 * Free the given SwrContext.
libswresample/swresample_internal.h+2−0
@@ -45,6 +45,8 @@ typedef struct SwrContext { //FIXME find unused fields · 44 unmodified lines
4545 int out_sample_rate;
4646 int flags;
4747 float slev, clev, rematrix_volume;
48+ const int *channel_map; ///< channel index (or -1 if muted channel) map
49+ int used_ch_count; ///< number of used channels (mapped channel count if channel_map, otherwise in.ch_count)
4850
4951 //below are private
5052 int int_bps;
libswresample/swresample_test.c+5−3
@@ -131,9 +131,11 @@ int main(int argc, char **argv){ · 130 unmodified lines
131131 in_sample_rate, out_sample_rate,
132132 av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt));
133133 forw_ctx = swr_alloc2(forw_ctx, out_ch_layout, out_sample_fmt+planar_out, out_sample_rate,
134− in_ch_layout, in_sample_fmt+planar_in , in_sample_rate, 0, 0);
135− backw_ctx = swr_alloc2(backw_ctx,in_ch_layout, in_sample_fmt, in_sample_rate,
136− out_ch_layout, out_sample_fmt+planar_out, out_sample_rate, 0, 0);
134+ in_ch_layout, in_sample_fmt+planar_in , in_sample_rate,
135+ NULL, 0, 0);
136+ backw_ctx = swr_alloc2(backw_ctx,in_ch_layout, in_sample_fmt, in_sample_rate,
137+ out_ch_layout, out_sample_fmt+planar_out, out_sample_rate,
138+ NULL, 0, 0);
137139 if(swr_init( forw_ctx) < 0)
138140 fprintf(stderr, "swr_init(->) failed\n");
139141 if(swr_init(backw_ctx) < 0)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t