mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-28 20:53:54 +02:00
lavfi/af_channelsplit: support arbitrary channel layouts
Not just those containing channel values under 64. Also, remove an arbitrary limitation on channel count.
This commit is contained in:
parent
7dc81d33c2
commit
18d492ff41
@ -34,15 +34,13 @@
|
||||
#include "filters.h"
|
||||
#include "formats.h"
|
||||
|
||||
#define MAX_CH 64
|
||||
|
||||
typedef struct ChannelSplitContext {
|
||||
const AVClass *class;
|
||||
|
||||
AVChannelLayout channel_layout;
|
||||
char *channels_str;
|
||||
|
||||
int map[64];
|
||||
int *map;
|
||||
} ChannelSplitContext;
|
||||
|
||||
#define OFFSET(x) offsetof(ChannelSplitContext, x)
|
||||
@ -71,10 +69,9 @@ static av_cold int init(AVFilterContext *ctx)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (channel_layout.nb_channels > MAX_CH) {
|
||||
av_log(ctx, AV_LOG_ERROR, "Too many channels\n");
|
||||
goto fail;
|
||||
}
|
||||
s->map = av_calloc(channel_layout.nb_channels, sizeof(*s->map));
|
||||
if (!s->map)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
for (i = 0; i < channel_layout.nb_channels; i++) {
|
||||
enum AVChannel channel = av_channel_layout_channel_from_index(&channel_layout, i);
|
||||
@ -118,6 +115,7 @@ static av_cold void uninit(AVFilterContext *ctx)
|
||||
ChannelSplitContext *s = ctx->priv;
|
||||
|
||||
av_channel_layout_uninit(&s->channel_layout);
|
||||
av_freep(&s->map);
|
||||
}
|
||||
|
||||
static int query_formats(AVFilterContext *ctx)
|
||||
@ -139,9 +137,27 @@ static int query_formats(AVFilterContext *ctx)
|
||||
AVFilterChannelLayouts *out_layouts = NULL;
|
||||
enum AVChannel channel = av_channel_layout_channel_from_index(&s->channel_layout, s->map[i]);
|
||||
|
||||
if ((ret = av_channel_layout_from_mask(&channel_layout, 1ULL << channel)) < 0 ||
|
||||
(ret = ff_add_channel_layout(&out_layouts, &channel_layout)) < 0 ||
|
||||
(ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts)) < 0)
|
||||
channel_layout.u.map = av_mallocz(sizeof(*channel_layout.u.map));
|
||||
if (!channel_layout.u.map)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
channel_layout.u.map[0].id = channel;
|
||||
channel_layout.nb_channels = 1;
|
||||
channel_layout.order = AV_CHANNEL_ORDER_CUSTOM;
|
||||
|
||||
ret = av_channel_layout_retype(&channel_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
|
||||
if (ret < 0) {
|
||||
av_channel_layout_uninit(&channel_layout);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ff_add_channel_layout(&out_layouts, &channel_layout);
|
||||
av_channel_layout_uninit(&channel_layout);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -154,17 +170,16 @@ static int filter_frame(AVFilterLink *outlink, AVFrame *buf)
|
||||
AVFilterContext *ctx = outlink->src;
|
||||
ChannelSplitContext *s = ctx->priv;
|
||||
const int i = FF_OUTLINK_IDX(outlink);
|
||||
enum AVChannel channel = av_channel_layout_channel_from_index(&buf->ch_layout, s->map[i]);
|
||||
int ret;
|
||||
|
||||
av_assert1(channel >= 0);
|
||||
|
||||
buf_out = av_frame_clone(buf);
|
||||
if (!buf_out)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[s->map[i]];
|
||||
ret = av_channel_layout_from_mask(&buf_out->ch_layout, 1ULL << channel);
|
||||
|
||||
av_channel_layout_uninit(&buf_out->ch_layout);
|
||||
ret = av_channel_layout_copy(&buf_out->ch_layout, &outlink->ch_layout);
|
||||
if (ret < 0) {
|
||||
av_frame_free(&buf_out);
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user