Not just those containing channel values under 64. Also, remove an arbitrary limitation on channel count.
Unified · Split
| @@ -34,15 +34,13 @@ · 33 unmodified lines | ||
| 34 | 34 | #include "filters.h" |
| 35 | 35 | #include "formats.h" |
| 36 | 36 | |
| 37 | −#define MAX_CH 64 | |
| 38 | − | |
| 39 | 37 | typedef struct ChannelSplitContext { |
| 40 | 38 | const AVClass *class; |
| 41 | 39 | |
| 42 | 40 | AVChannelLayout channel_layout; |
| 43 | 41 | char *channels_str; |
| 44 | 42 | |
| 45 | − int map[64]; | |
| 43 | + int *map; | |
| 46 | 44 | } ChannelSplitContext; |
| 47 | 45 | |
| 48 | 46 | #define OFFSET(x) offsetof(ChannelSplitContext, x) |
| @@ -71,10 +69,9 @@ static av_cold int init(AVFilterContext *ctx) · 22 unmodified lines | ||
| 71 | 69 | goto fail; |
| 72 | 70 | } |
| 73 | 71 | |
| 74 | − if (channel_layout.nb_channels > MAX_CH) { | |
| 75 | − av_log(ctx, AV_LOG_ERROR, "Too many channels\n"); | |
| 76 | − goto fail; | |
| 77 | − } | |
| 72 | + s->map = av_calloc(channel_layout.nb_channels, sizeof(*s->map)); | |
| 73 | + if (!s->map) | |
| 74 | + return AVERROR(ENOMEM); | |
| 78 | 75 | |
| 79 | 76 | for (i = 0; i < channel_layout.nb_channels; i++) { |
| 80 | 77 | enum AVChannel channel = av_channel_layout_channel_from_index(&channel_layout, i); |
| @@ -118,6 +115,7 @@ static av_cold void uninit(AVFilterContext *ctx) · 37 unmodified lines | ||
| 118 | 115 | ChannelSplitContext *s = ctx->priv; |
| 119 | 116 | |
| 120 | 117 | av_channel_layout_uninit(&s->channel_layout); |
| 118 | + av_freep(&s->map); | |
| 121 | 119 | } |
| 122 | 120 | |
| 123 | 121 | static int query_formats(AVFilterContext *ctx) |
| @@ -139,9 +137,27 @@ static int query_formats(AVFilterContext *ctx) · 15 unmodified lines | ||
| 139 | 137 | AVFilterChannelLayouts *out_layouts = NULL; |
| 140 | 138 | enum AVChannel channel = av_channel_layout_channel_from_index(&s->channel_layout, s->map[i]); |
| 141 | 139 | |
| 142 | − if ((ret = av_channel_layout_from_mask(&channel_layout, 1ULL << channel)) < 0 || | |
| 143 | − (ret = ff_add_channel_layout(&out_layouts, &channel_layout)) < 0 || | |
| 144 | − (ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts)) < 0) | |
| 140 | + channel_layout.u.map = av_mallocz(sizeof(*channel_layout.u.map)); | |
| 141 | + if (!channel_layout.u.map) | |
| 142 | + return AVERROR(ENOMEM); | |
| 143 | + | |
| 144 | + channel_layout.u.map[0].id = channel; | |
| 145 | + channel_layout.nb_channels = 1; | |
| 146 | + channel_layout.order = AV_CHANNEL_ORDER_CUSTOM; | |
| 147 | + | |
| 148 | + ret = av_channel_layout_retype(&channel_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL); | |
| 149 | + if (ret < 0) { | |
| 150 | + av_channel_layout_uninit(&channel_layout); | |
| 151 | + return ret; | |
| 152 | + } | |
| 153 | + | |
| 154 | + ret = ff_add_channel_layout(&out_layouts, &channel_layout); | |
| 155 | + av_channel_layout_uninit(&channel_layout); | |
| 156 | + if (ret < 0) | |
| 157 | + return ret; | |
| 158 | + | |
| 159 | + ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts); | |
| 160 | + if (ret < 0) | |
| 145 | 161 | return ret; |
| 146 | 162 | } |
| 147 | 163 | |
| @@ -154,17 +170,16 @@ static int filter_frame(AVFilterLink *outlink, AVFrame *buf) · 6 unmodified lines | ||
| 154 | 170 | AVFilterContext *ctx = outlink->src; |
| 155 | 171 | ChannelSplitContext *s = ctx->priv; |
| 156 | 172 | const int i = FF_OUTLINK_IDX(outlink); |
| 157 | − enum AVChannel channel = av_channel_layout_channel_from_index(&buf->ch_layout, s->map[i]); | |
| 158 | 173 | int ret; |
| 159 | 174 | |
| 160 | − av_assert1(channel >= 0); | |
| 161 | − | |
| 162 | 175 | buf_out = av_frame_clone(buf); |
| 163 | 176 | if (!buf_out) |
| 164 | 177 | return AVERROR(ENOMEM); |
| 165 | 178 | |
| 166 | 179 | buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[s->map[i]]; |
| 167 | − ret = av_channel_layout_from_mask(&buf_out->ch_layout, 1ULL << channel); | |
| 180 | + | |
| 181 | + av_channel_layout_uninit(&buf_out->ch_layout); | |
| 182 | + ret = av_channel_layout_copy(&buf_out->ch_layout, &outlink->ch_layout); | |
| 168 | 183 | if (ret < 0) { |
| 169 | 184 | av_frame_free(&buf_out); |
| 170 | 185 | return ret; |