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 | #include "filters.h" | 34 | #include "filters.h" |
| 35 | #include "formats.h" | 35 | #include "formats.h" |
| 36 | 36 | ||
| 37 | #define MAX_CH 64 | ||
| 38 | |||
| 39 | typedef struct ChannelSplitContext { | 37 | typedef struct ChannelSplitContext { |
| 40 | const AVClass *class; | 38 | const AVClass *class; |
| 41 | 39 | ||
| 42 | AVChannelLayout channel_layout; | 40 | AVChannelLayout channel_layout; |
| 43 | char *channels_str; | 41 | char *channels_str; |
| 44 | 42 | ||
| 45 | int map[64]; | 43 | int *map; |
| 46 | } ChannelSplitContext; | 44 | } ChannelSplitContext; |
| 47 | 45 | ||
| 48 | #define OFFSET(x) offsetof(ChannelSplitContext, x) | 46 | #define OFFSET(x) offsetof(ChannelSplitContext, x) |
| @@ -71,10 +69,9 @@ static av_cold int init(AVFilterContext *ctx) · 22 unmodified lines | |||
| 71 | goto fail; | 69 | goto fail; |
| 72 | } | 70 | } |
| 73 | 71 | ||
| 74 | if (channel_layout.nb_channels > MAX_CH) { | 72 | s->map = av_calloc(channel_layout.nb_channels, sizeof(*s->map)); |
| 75 | av_log(ctx, AV_LOG_ERROR, "Too many channels\n"); | 73 | if (!s->map) |
| 76 | goto fail; | 74 | return AVERROR(ENOMEM); |
| 77 | } | ||
| 78 | 75 | ||
| 79 | for (i = 0; i < channel_layout.nb_channels; i++) { | 76 | for (i = 0; i < channel_layout.nb_channels; i++) { |
| 80 | enum AVChannel channel = av_channel_layout_channel_from_index(&channel_layout, i); | 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 | ChannelSplitContext *s = ctx->priv; | 115 | ChannelSplitContext *s = ctx->priv; |
| 119 | 116 | ||
| 120 | av_channel_layout_uninit(&s->channel_layout); | 117 | av_channel_layout_uninit(&s->channel_layout); |
| 118 | av_freep(&s->map); | ||
| 121 | } | 119 | } |
| 122 | 120 | ||
| 123 | static int query_formats(AVFilterContext *ctx) | 121 | static int query_formats(AVFilterContext *ctx) |
| @@ -139,9 +137,27 @@ static int query_formats(AVFilterContext *ctx) · 15 unmodified lines | |||
| 139 | AVFilterChannelLayouts *out_layouts = NULL; | 137 | AVFilterChannelLayouts *out_layouts = NULL; |
| 140 | enum AVChannel channel = av_channel_layout_channel_from_index(&s->channel_layout, s->map[i]); | 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 || | 140 | channel_layout.u.map = av_mallocz(sizeof(*channel_layout.u.map)); |
| 143 | (ret = ff_add_channel_layout(&out_layouts, &channel_layout)) < 0 || | 141 | if (!channel_layout.u.map) |
| 144 | (ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts)) < 0) | 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 | return ret; | 161 | return ret; |
| 146 | } | 162 | } |
| 147 | 163 | ||
| @@ -154,17 +170,16 @@ static int filter_frame(AVFilterLink *outlink, AVFrame *buf) · 6 unmodified lines | |||
| 154 | AVFilterContext *ctx = outlink->src; | 170 | AVFilterContext *ctx = outlink->src; |
| 155 | ChannelSplitContext *s = ctx->priv; | 171 | ChannelSplitContext *s = ctx->priv; |
| 156 | const int i = FF_OUTLINK_IDX(outlink); | 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 | int ret; | 173 | int ret; |
| 159 | 174 | ||
| 160 | av_assert1(channel >= 0); | ||
| 161 | |||
| 162 | buf_out = av_frame_clone(buf); | 175 | buf_out = av_frame_clone(buf); |
| 163 | if (!buf_out) | 176 | if (!buf_out) |
| 164 | return AVERROR(ENOMEM); | 177 | return AVERROR(ENOMEM); |
| 165 | 178 | ||
| 166 | buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[s->map[i]]; | 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 | if (ret < 0) { | 183 | if (ret < 0) { |
| 169 | av_frame_free(&buf_out); | 184 | av_frame_free(&buf_out); |
| 170 | return ret; | 185 | return ret; |