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
35struct AVAudioConvert {35struct AVAudioConvert {
36 int channels;36 int channels;
37 int fmt_pair;37 int fmt_pair;
38 const int *ch_map;
38};39};
39 40
40AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt,41AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt,
41 enum AVSampleFormat in_fmt,42 enum AVSampleFormat in_fmt,
42 int channels, int flags)43 int channels, const int *ch_map,
44 int flags)
43{45{
44 AVAudioConvert *ctx;46 AVAudioConvert *ctx;
45 ctx = av_malloc(sizeof(AVAudioConvert));47 ctx = av_malloc(sizeof(AVAudioConvert));
@@ -47,6 +49,7 @@ AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt, · 1 unmodified line
47 return NULL;49 return NULL;
48 ctx->channels = channels;50 ctx->channels = channels;
49 ctx->fmt_pair = out_fmt + AV_SAMPLE_FMT_NB*in_fmt;51 ctx->fmt_pair = out_fmt + AV_SAMPLE_FMT_NB*in_fmt;
52 ctx->ch_map = ch_map;
50 return ctx;53 return ctx;
51}54}
52 55
@@ -58,15 +61,17 @@ void swr_audio_convert_free(AVAudioConvert **ctx) · 5 unmodified lines
58int swr_audio_convert(AVAudioConvert *ctx, AudioData *out, AudioData*in, int len)61int swr_audio_convert(AVAudioConvert *ctx, AudioData *out, AudioData*in, int len)
59{62{
60 int ch;63 int ch;
64 const uint8_t null_input[8] = {0};
61 65
62 av_assert0(ctx->channels == out->ch_count);66 av_assert0(ctx->channels == out->ch_count);
63 67
64 //FIXME optimize common cases68 //FIXME optimize common cases
65 69
66 for(ch=0; ch<ctx->channels; ch++){70 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;
68 const int os= (out->planar ? 1 :out->ch_count) *out->bps;73 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];
70 uint8_t *po= out->ch[ch];75 uint8_t *po= out->ch[ch];
71 uint8_t *end= po + os*len;76 uint8_t *end= po + os*len;
72 if(!po)77 if(!po)
libswresample/audioconvert.h+4−1
@@ -42,11 +42,14 @@ typedef struct AVAudioConvert AVAudioConvert; · 41 unmodified lines
42 * @param in_fmt Input sample format42 * @param in_fmt Input sample format
43 * @param channels Number of channels43 * @param channels Number of channels
44 * @param flags See AV_CPU_FLAG_xx44 * @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
45 * @return NULL on error47 * @return NULL on error
46 */48 */
47AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt,49AVAudioConvert *swr_audio_convert_alloc(enum AVSampleFormat out_fmt,
48 enum AVSampleFormat in_fmt,50 enum AVSampleFormat in_fmt,
49 int channels, int flags);51 int channels, const int *ch_map,
52 int flags);
50 53
51/**54/**
52 * Free audio sample format converter context.55 * Free audio sample format converter context.
libswresample/swresample.c+23−9
@@ -38,6 +38,7 @@ · 37 unmodified lines
38static const AVOption options[]={38static const AVOption options[]={
39{"ich", "input channel count", OFFSET( in.ch_count ), AV_OPT_TYPE_INT, {.dbl=2}, 1, SWR_CH_MAX, 0},39{"ich", "input channel count", OFFSET( in.ch_count ), AV_OPT_TYPE_INT, {.dbl=2}, 1, SWR_CH_MAX, 0},
40{"och", "output channel count", OFFSET(out.ch_count ), AV_OPT_TYPE_INT, {.dbl=2}, 1, SWR_CH_MAX, 0},40{"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},
41{"isr", "input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT, {.dbl=48000}, 1, INT_MAX, 0},42{"isr", "input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT, {.dbl=48000}, 1, INT_MAX, 0},
42{"osr", "output sample rate" , OFFSET(out_sample_rate), AV_OPT_TYPE_INT, {.dbl=48000}, 1, INT_MAX, 0},43{"osr", "output sample rate" , OFFSET(out_sample_rate), AV_OPT_TYPE_INT, {.dbl=48000}, 1, INT_MAX, 0},
43//{"ip" , "input planar" , OFFSET( in.planar ), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1, 0},44//{"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
76 77
77SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,78SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
78 int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,79 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){
80 if(!s) s= swr_alloc();81 if(!s) s= swr_alloc();
81 if(!s) return NULL;82 if(!s) return NULL;
82 83
@@ -90,9 +91,11 @@ SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampl · 7 unmodified lines
90 av_set_int(s, "isf", in_sample_fmt);91 av_set_int(s, "isf", in_sample_fmt);
91 av_set_int(s, "isr", in_sample_rate);92 av_set_int(s, "isr", in_sample_rate);
92 93
94 s->channel_map = channel_map;
93 s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);95 s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);
94 s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);96 s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);
95 s->int_sample_fmt = AV_SAMPLE_FMT_S16;97 s->int_sample_fmt = AV_SAMPLE_FMT_S16;
98 s->used_ch_count= s-> in.ch_count;
96 99
97 return s;100 return s;
98}101}
@@ -167,13 +170,16 @@ int swr_init(SwrContext *s){ · 68 unmodified lines
167 return -1;170 return -1;
168 }171 }
169 172
170 if(s-> in.ch_count && s-> in_ch_layout && s->in.ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){173 if(!s->used_ch_count)
171 av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than there actually is, ignoring layout\n");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");
172 s-> in_ch_layout= 0;178 s-> in_ch_layout= 0;
173 }179 }
174 180
175 if(!s-> in_ch_layout)181 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);
177 if(!s->out_ch_layout)183 if(!s->out_ch_layout)
178 s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count);184 s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count);
179 185
@@ -182,10 +188,13 @@ int swr_init(SwrContext *s){ · 2 unmodified lines
182#define RSC 1 //FIXME finetune188#define RSC 1 //FIXME finetune
183 if(!s-> in.ch_count)189 if(!s-> in.ch_count)
184 s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout);190 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;
185 if(!s->out.ch_count)193 if(!s->out.ch_count)
186 s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);194 s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout);
187 195
188av_assert0(s-> in.ch_count);196av_assert0(s-> in.ch_count);
197av_assert0(s->used_ch_count);
189av_assert0(s->out.ch_count);198av_assert0(s->out.ch_count);
190 s->resample_first= RSC*s->out.ch_count/s->in.ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0;199 s->resample_first= RSC*s->out.ch_count/s->in.ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0;
191 200
@@ -193,22 +202,27 @@ av_assert0(s->out.ch_count); · 1 unmodified line
193 s->int_bps= av_get_bits_per_sample_fmt(s->int_sample_fmt)/8;202 s->int_bps= av_get_bits_per_sample_fmt(s->int_sample_fmt)/8;
194 s->out.bps= av_get_bits_per_sample_fmt(s->out_sample_fmt)/8;203 s->out.bps= av_get_bits_per_sample_fmt(s->out_sample_fmt)/8;
195 204
196 if(!s->resample && !s->rematrix){205 if(!s->resample && !s->rematrix && !s->channel_map){
197 s->full_convert = swr_audio_convert_alloc(s->out_sample_fmt,206 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);
199 return 0;208 return 0;
200 }209 }
201 210
202 s->in_convert = swr_audio_convert_alloc(s->int_sample_fmt,211 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);
204 s->out_convert= swr_audio_convert_alloc(s->out_sample_fmt,213 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);
206 215
207 216
208 s->postin= s->in;217 s->postin= s->in;
209 s->preout= s->out;218 s->preout= s->out;
210 s->midbuf= s->in;219 s->midbuf= s->in;
211 s->in_buffer= s->in;220 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 }
212 if(!s->resample_first){226 if(!s->resample_first){
213 s->midbuf.ch_count= s->out.ch_count;227 s->midbuf.ch_count= s->out.ch_count;
214 s->in_buffer.ch_count = s->out.ch_count;228 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
325 if((ret=realloc_audio(&s->postin, in_count))<0)339 if((ret=realloc_audio(&s->postin, in_count))<0)
326 return ret;340 return ret;
327 if(s->resample_first){341 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);
329 if((ret=realloc_audio(&s->midbuf, out_count))<0)343 if((ret=realloc_audio(&s->midbuf, out_count))<0)
330 return ret;344 return ret;
331 }else{345 }else{
libswresample/swresample.h+2−2
@@ -25,7 +25,7 @@ · 24 unmodified lines
25#include "libavutil/samplefmt.h"25#include "libavutil/samplefmt.h"
26 26
27#define LIBSWRESAMPLE_VERSION_MAJOR 027#define LIBSWRESAMPLE_VERSION_MAJOR 0
28#define LIBSWRESAMPLE_VERSION_MINOR 128#define LIBSWRESAMPLE_VERSION_MINOR 2
29#define LIBSWRESAMPLE_VERSION_MICRO 029#define LIBSWRESAMPLE_VERSION_MICRO 0
30 30
31#define SWR_CH_MAX 1631#define SWR_CH_MAX 16
@@ -57,7 +57,7 @@ int swr_init(struct SwrContext *s); · 25 unmodified lines
57 */57 */
58struct SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,58struct SwrContext *swr_alloc2(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
59 int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,59 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);
61 61
62/**62/**
63 * Free the given SwrContext.63 * Free the given SwrContext.
libswresample/swresample_internal.h+2−0
@@ -45,6 +45,8 @@ typedef struct SwrContext { //FIXME find unused fields · 44 unmodified lines
45 int out_sample_rate;45 int out_sample_rate;
46 int flags;46 int flags;
47 float slev, clev, rematrix_volume;47 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)
48 50
49 //below are private51 //below are private
50 int int_bps;52 int int_bps;
libswresample/swresample_test.c+5−3
@@ -131,9 +131,11 @@ int main(int argc, char **argv){ · 130 unmodified lines
131 in_sample_rate, out_sample_rate,131 in_sample_rate, out_sample_rate,
132 av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt));132 av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt));
133 forw_ctx = swr_alloc2(forw_ctx, out_ch_layout, out_sample_fmt+planar_out, out_sample_rate,133 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);134 in_ch_layout, in_sample_fmt+planar_in , in_sample_rate,
135 backw_ctx = swr_alloc2(backw_ctx,in_ch_layout, in_sample_fmt, in_sample_rate,135 NULL, 0, 0);
136 out_ch_layout, out_sample_fmt+planar_out, out_sample_rate, 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);
137 if(swr_init( forw_ctx) < 0)139 if(swr_init( forw_ctx) < 0)
138 fprintf(stderr, "swr_init(->) failed\n");140 fprintf(stderr, "swr_init(->) failed\n");
139 if(swr_init(backw_ctx) < 0)141 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