summaryrefslogtreecommitdiff
path: root/libavfilter/f_sidedata.c (plain)
blob: 45d246b73231c823b8154cb14fa7ab0896c1c038
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19/**
20 * @file
21 * filter for manipulating frame side data
22 */
23
24#include "libavutil/avassert.h"
25#include "libavutil/internal.h"
26#include "libavutil/frame.h"
27#include "libavutil/opt.h"
28#include "avfilter.h"
29#include "formats.h"
30#include "internal.h"
31
32enum SideDataMode {
33 SIDEDATA_SELECT,
34 SIDEDATA_DELETE,
35 SIDEDATA_NB
36};
37
38typedef struct SideDataContext {
39 const AVClass *class;
40
41 int mode;
42 enum AVFrameSideDataType type;
43} SideDataContext;
44
45#define OFFSET(x) offsetof(SideDataContext, x)
46#define DEFINE_OPTIONS(filt_name, FLAGS) \
47static const AVOption filt_name##_options[] = { \
48 { "mode", "set a mode of operation", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, SIDEDATA_NB-1, FLAGS, "mode" }, \
49 { "select", "select frame", 0, AV_OPT_TYPE_CONST, {.i64 = SIDEDATA_SELECT }, 0, 0, FLAGS, "mode" }, \
50 { "delete", "delete side data", 0, AV_OPT_TYPE_CONST, {.i64 = SIDEDATA_DELETE }, 0, 0, FLAGS, "mode" }, \
51 { "type", "set side data type", OFFSET(type), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, INT_MAX, FLAGS, "type" }, \
52 { "PANSCAN", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_PANSCAN }, 0, 0, FLAGS, "type" }, \
53 { "A53_CC", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_A53_CC }, 0, 0, FLAGS, "type" }, \
54 { "STEREO3D", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_STEREO3D }, 0, 0, FLAGS, "type" }, \
55 { "MATRIXENCODING", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_MATRIXENCODING }, 0, 0, FLAGS, "type" }, \
56 { "DOWNMIX_INFO", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_DOWNMIX_INFO }, 0, 0, FLAGS, "type" }, \
57 { "REPLAYGAIN", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_REPLAYGAIN }, 0, 0, FLAGS, "type" }, \
58 { "DISPLAYMATRIX", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_DISPLAYMATRIX }, 0, 0, FLAGS, "type" }, \
59 { "AFD", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_AFD }, 0, 0, FLAGS, "type" }, \
60 { "MOTION_VECTORS", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_MOTION_VECTORS }, 0, 0, FLAGS, "type" }, \
61 { "SKIP_SAMPLES", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_SKIP_SAMPLES }, 0, 0, FLAGS, "type" }, \
62 { "AUDIO_SERVICE_TYPE", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_AUDIO_SERVICE_TYPE }, 0, 0, FLAGS, "type" }, \
63 { "MASTERING_DISPLAY_METADATA", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_MASTERING_DISPLAY_METADATA }, 0, 0, FLAGS, "type" }, \
64 { "GOP_TIMECODE", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_GOP_TIMECODE }, 0, 0, FLAGS, "type" }, \
65 { NULL } \
66}
67
68static av_cold int init(AVFilterContext *ctx)
69{
70 SideDataContext *s = ctx->priv;
71
72 if (s->type == -1 && s->mode != SIDEDATA_DELETE) {
73 av_log(ctx, AV_LOG_ERROR, "Side data type must be set\n");
74 return AVERROR(EINVAL);
75 }
76
77 return 0;
78}
79
80static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
81{
82 AVFilterContext *ctx = inlink->dst;
83 AVFilterLink *outlink = ctx->outputs[0];
84 SideDataContext *s = ctx->priv;
85 AVFrameSideData *sd = NULL;
86
87 if (s->type != -1)
88 sd = av_frame_get_side_data(frame, s->type);
89
90 switch (s->mode) {
91 case SIDEDATA_SELECT:
92 if (sd) {
93 return ff_filter_frame(outlink, frame);
94 }
95 break;
96 case SIDEDATA_DELETE:
97 if (s->type == -1) {
98 while (frame->nb_side_data)
99 av_frame_remove_side_data(frame, frame->side_data[0]->type);
100 } else if (sd) {
101 av_frame_remove_side_data(frame, s->type);
102 }
103 return ff_filter_frame(outlink, frame);
104 break;
105 default:
106 av_assert0(0);
107 };
108
109 av_frame_free(&frame);
110
111 return 0;
112}
113
114#if CONFIG_ASIDEDATA_FILTER
115
116DEFINE_OPTIONS(asidedata, AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM);
117AVFILTER_DEFINE_CLASS(asidedata);
118
119static const AVFilterPad ainputs[] = {
120 {
121 .name = "default",
122 .type = AVMEDIA_TYPE_AUDIO,
123 .filter_frame = filter_frame,
124 },
125 { NULL }
126};
127
128static const AVFilterPad aoutputs[] = {
129 {
130 .name = "default",
131 .type = AVMEDIA_TYPE_AUDIO,
132 },
133 { NULL }
134};
135
136AVFilter ff_af_asidedata = {
137 .name = "asidedata",
138 .description = NULL_IF_CONFIG_SMALL("Manipulate audio frame side data."),
139 .priv_size = sizeof(SideDataContext),
140 .priv_class = &asidedata_class,
141 .init = init,
142 .inputs = ainputs,
143 .outputs = aoutputs,
144 .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
145};
146#endif /* CONFIG_ASIDEDATA_FILTER */
147
148#if CONFIG_SIDEDATA_FILTER
149
150DEFINE_OPTIONS(sidedata, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM);
151AVFILTER_DEFINE_CLASS(sidedata);
152
153static const AVFilterPad inputs[] = {
154 {
155 .name = "default",
156 .type = AVMEDIA_TYPE_VIDEO,
157 .filter_frame = filter_frame,
158 },
159 { NULL }
160};
161
162static const AVFilterPad outputs[] = {
163 {
164 .name = "default",
165 .type = AVMEDIA_TYPE_VIDEO,
166 },
167 { NULL }
168};
169
170AVFilter ff_vf_sidedata = {
171 .name = "sidedata",
172 .description = NULL_IF_CONFIG_SMALL("Manipulate video frame side data."),
173 .priv_size = sizeof(SideDataContext),
174 .priv_class = &sidedata_class,
175 .init = init,
176 .inputs = inputs,
177 .outputs = outputs,
178 .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
179};
180#endif /* CONFIG_SIDEDATA_FILTER */
181