FFmpeg
Loading...
Searching...
No Matches
filter_units.c
Go to the documentation of this file.
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#include <stdbool.h>
20#include <stdlib.h>
21
22#include "libavutil/mem.h"
23#include "libavutil/opt.h"
24
25#include "libavcodec/bsf.h"
27#include "libavcodec/cbs.h"
28#include "libavcodec/cbs_bsf.h"
29
30
31typedef struct FilterUnitsContext {
32 const AVClass *class;
33
36
37 const char *pass_types;
38 const char *remove_types;
39 /* enum AVDiscard, use int for AVOption */
42
43 enum {
52
53
54static int filter_units_make_type_list(const char *list_string,
55 CodedBitstreamUnitType **type_list,
56 int *nb_types)
57{
59 int pass, count;
60
61 for (pass = 1; pass <= 2; pass++) {
62 long value, range_start, range_end;
63 const char *str;
64 char *value_end;
65
66 count = 0;
67 for (str = list_string; *str;) {
68 value = strtol(str, &value_end, 0);
69 if (str == value_end)
70 goto invalid;
71 str = (const char *)value_end;
72 if (*str == '-') {
73 ++str;
74 range_start = value;
75 range_end = strtol(str, &value_end, 0);
76 if (str == value_end)
77 goto invalid;
78
79 for (value = range_start; value < range_end; value++) {
80 if (pass == 2)
81 list[count] = value;
82 ++count;
83 }
84 } else {
85 if (pass == 2)
86 list[count] = value;
87 ++count;
88 }
89 if (*str == '|')
90 ++str;
91 }
92 if (pass == 1) {
93 list = av_malloc_array(count, sizeof(*list));
94 if (!list)
95 return AVERROR(ENOMEM);
96 }
97 }
98
99 *type_list = list;
100 *nb_types = count;
101 return 0;
102
103invalid:
104 av_freep(&list);
105 return AVERROR(EINVAL);
106}
107
109{
111 CodedBitstreamFragment *frag = &ctx->fragment;
112 int err, i, j;
113
114 err = ff_bsf_get_packet_ref(bsf, pkt);
115 if (err < 0)
116 return err;
117
118 if (ctx->passthrough)
119 return 0;
120
121 err = ff_cbs_read_packet(ctx->cbc, frag, pkt);
122 if (err < 0) {
123 av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
124 goto fail;
125 }
126
127 ff_cbs_discard_units(ctx->cbc, frag, ctx->discard, ctx->discard_flags);
128 if (ctx->mode != NOOP) {
129 for (i = frag->nb_units - 1; i >= 0; i--) {
130 for (j = 0; j < ctx->nb_types; j++) {
131 if (frag->units[i].type == ctx->type_list[j])
132 break;
133 }
134 if (ctx->mode == REMOVE ? j < ctx->nb_types
135 : j >= ctx->nb_types)
136 ff_cbs_delete_unit(frag, i);
137 }
138 }
139
140 if (frag->nb_units == 0) {
141 // Don't return packets with nothing in them.
142 err = AVERROR(EAGAIN);
143 goto fail;
144 }
145
146 err = ff_cbs_write_packet(ctx->cbc, pkt, frag);
147 if (err < 0) {
148 av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n");
149 goto fail;
150 }
151
152fail:
153 if (err < 0)
155 ff_cbs_fragment_reset(frag);
156
157 return err;
158}
159
161{
163 int err;
164
165 if (ctx->pass_types && ctx->remove_types) {
166 av_log(bsf, AV_LOG_ERROR, "Exactly one of pass_types or "
167 "remove_types is required.\n");
168 return AVERROR(EINVAL);
169 }
170
171 if (ctx->pass_types) {
172 ctx->mode = PASS;
173 err = filter_units_make_type_list(ctx->pass_types,
174 &ctx->type_list, &ctx->nb_types);
175 if (err < 0) {
176 av_log(bsf, AV_LOG_ERROR, "Failed to parse pass_types.\n");
177 return err;
178 }
179 } else if (ctx->remove_types) {
180 ctx->mode = REMOVE;
181 err = filter_units_make_type_list(ctx->remove_types,
182 &ctx->type_list, &ctx->nb_types);
183 if (err < 0) {
184 av_log(bsf, AV_LOG_ERROR, "Failed to parse remove_types.\n");
185 return err;
186 }
187 } else if (ctx->discard == AVDISCARD_NONE) {
188 ctx->passthrough = true;
189 return 0;
190 }
191
192 err = ff_cbs_init(&ctx->cbc, bsf->par_in->codec_id, bsf);
193 if (err < 0)
194 return err;
195
196 if (ctx->discard == AVDISCARD_NONE) {
197 // Don't actually decompose anything, we only want the unit data.
198 ctx->cbc->decompose_unit_types = ctx->type_list;
199 ctx->cbc->nb_decompose_unit_types = 0;
200 }
201
202 if (bsf->par_in->extradata) {
203 CodedBitstreamFragment *frag = &ctx->fragment;
204
205 err = ff_cbs_read_extradata(ctx->cbc, frag, bsf->par_in);
206 if (err < 0) {
207 av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n");
208 } else {
209 err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, frag);
210 if (err < 0)
211 av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n");
212 }
213
214 ff_cbs_fragment_reset(frag);
215 }
216
217 return err;
218}
219
221{
223
224 av_freep(&ctx->type_list);
225
226 ff_cbs_fragment_free(&ctx->fragment);
227 ff_cbs_close(&ctx->cbc);
228}
229
230#define OFFSET(x) offsetof(FilterUnitsContext, x)
231#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
233 { "pass_types", "List of unit types to pass through the filter.",
234 OFFSET(pass_types), AV_OPT_TYPE_STRING,
235 { .str = NULL }, .flags = FLAGS },
236 { "remove_types", "List of unit types to remove in the filter.",
237 OFFSET(remove_types), AV_OPT_TYPE_STRING,
238 { .str = NULL }, .flags = FLAGS },
239
240 { "discard", "Remove the selected frames",
241 OFFSET(discard), AV_OPT_TYPE_INT,
242 { .i64 = AVDISCARD_NONE }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
243 { "none" , "discard none",
245 { .i64 = AVDISCARD_NONE }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
246 { "default" , "discard none, but can be changed after dynamically",
248 { .i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
249 { "nonref", "discard all non-reference frames",
251 { .i64 = AVDISCARD_NONREF }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
252 { "bidir", "discard all bidirectional frames",
254 { .i64 = AVDISCARD_BIDIR }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
255 { "nonintra", "discard all frames except I frames",
257 { .i64 = AVDISCARD_NONINTRA }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
258 { "nonkey", "discard all frames except keyframes",
260 { .i64 = AVDISCARD_NONKEY }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
261 { "all", "discard all frames",
263 { .i64 = AVDISCARD_ALL }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
264
265 { "discard_flags", "flags to control the discard frame behavior",
266 OFFSET(discard_flags), AV_OPT_TYPE_FLAGS,
267 { .i64 = DISCARD_FLAG_NONE }, INT_MIN, INT_MAX, FLAGS, .unit = "discard_flags"},
268 { "keep_non_vcl", "non-vcl units even if the picture has been dropped",
270 { .i64 = DISCARD_FLAG_KEEP_NON_VCL }, INT_MIN, INT_MAX, FLAGS, .unit = "discard_flags"},
271 { NULL }
272};
273
275 .class_name = "filter_units",
276 .item_name = av_default_item_name,
277 .option = filter_units_options,
278 .version = LIBAVUTIL_VERSION_INT,
279};
280
282 .p.name = "filter_units",
283 .p.codec_ids = ff_cbs_all_codec_ids,
284 .p.priv_class = &filter_units_class,
285 .priv_data_size = sizeof(FilterUnitsContext),
289};
static AVFormatContext * ctx
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
const FFBitStreamFilter ff_filter_units_bsf
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition bsf.c:254
enum AVCodecID ff_cbs_all_codec_ids[]
Table of all supported codec IDs.
Definition cbs_bsf.c:25
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define FLAGS
Definition cmdutils.c:598
#define NULL
Definition coverity.c:32
static AVPacket * pkt
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
double value
Definition eval.c:102
static int filter_units_make_type_list(const char *list_string, CodedBitstreamUnitType **type_list, int *nb_types)
static int filter_units_filter(AVBSFContext *bsf, AVPacket *pkt)
static int filter_units_init(AVBSFContext *bsf)
static void filter_units_close(AVBSFContext *bsf)
static const AVClass filter_units_class
static const AVOption filter_units_options[]
#define OFFSET(x)
#define fail
Definition test.h:479
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition opt.h:254
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
@ AVDISCARD_ALL
discard all
Definition defs.h:232
@ AVDISCARD_NONKEY
discard all frames except keyframes
Definition defs.h:231
@ AVDISCARD_BIDIR
discard all bidirectional frames
Definition defs.h:229
@ AVDISCARD_DEFAULT
discard useless packets like 0 size packets in avi
Definition defs.h:227
@ AVDISCARD_NONE
discard nothing
Definition defs.h:226
@ AVDISCARD_NONINTRA
discard all non intra frames
Definition defs.h:230
@ AVDISCARD_NONREF
discard all non reference
Definition defs.h:228
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
@ DISCARD_FLAG_KEEP_NON_VCL
keep non-vcl units even if the picture has been dropped.
Definition cbs.h:507
@ DISCARD_FLAG_NONE
Definition cbs.h:502
uint32_t CodedBitstreamUnitType
The codec-specific type of a bitstream unit.
Definition cbs.h:66
Memory handling functions.
AVOptions.
The bitstream filter state.
Definition bsf.h:68
void * priv_data
Opaque filter-specific private data.
Definition bsf.h:83
AVCodecParameters * par_in
Parameters of the input stream.
Definition bsf.h:90
AVCodecParameters * par_out
Parameters of the output stream.
Definition bsf.h:96
Describe the class of an AVClass context structure.
Definition log.h:76
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition codec_par.h:71
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
Context structure for coded bitstream operations.
Definition cbs.h:226
Coded bitstream fragment structure, combining one or more units.
Definition cbs.h:129
CodedBitstreamUnit * units
Pointer to an array of units of length nb_units_allocated.
Definition cbs.h:175
int nb_units
Number of units in this fragment.
Definition cbs.h:160
CodedBitstreamUnitType type
Codec-specific type of this unit.
Definition cbs.h:81
CodedBitstreamFragment fragment
CodedBitstreamUnitType * type_list
const char * remove_types
const char * pass_types
CodedBitstreamContext * cbc
Definition swscale.c:71
#define av_malloc_array(a, b)
#define av_freep(p)
#define av_log(a,...)
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29