FFmpeg
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 "bsf.h"
26 #include "bsf_internal.h"
27 #include "cbs.h"
28 #include "cbs_bsf.h"
29 
30 
31 typedef 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 */
40  int discard;
42 
43  enum {
47  } mode;
49  int nb_types;
52 
53 
54 static 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 
103 invalid:
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 
152 fail:
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)
232 static const AVOption filter_units_options[] = {
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 
274 static const AVClass filter_units_class = {
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 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:433
AVBSFContext::par_in
AVCodecParameters * par_in
Parameters of the input stream.
Definition: bsf.h:90
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:71
FilterUnitsContext::pass_types
const char * pass_types
Definition: filter_units.c:37
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
bsf_internal.h
opt.h
AVBitStreamFilter::name
const char * name
Definition: bsf.h:112
FilterUnitsContext::cbc
CodedBitstreamContext * cbc
Definition: filter_units.c:34
CodedBitstreamContext
Context structure for coded bitstream operations.
Definition: cbs.h:226
AVOption
AVOption.
Definition: opt.h:429
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
CodedBitstreamUnit::type
CodedBitstreamUnitType type
Codec-specific type of this unit.
Definition: cbs.h:81
FilterUnitsContext::PASS
@ PASS
Definition: filter_units.c:45
FilterUnitsContext::remove_types
const char * remove_types
Definition: filter_units.c:38
filter_units_make_type_list
static int filter_units_make_type_list(const char *list_string, CodedBitstreamUnitType **type_list, int *nb_types)
Definition: filter_units.c:54
AVBSFContext
The bitstream filter state.
Definition: bsf.h:68
FLAGS
#define FLAGS
Definition: filter_units.c:231
close
static av_cold void close(AVCodecParserContext *s)
Definition: apv_parser.c:197
bsf.h
cbs_bsf.h
fail
#define fail()
Definition: checkasm.h:224
OFFSET
#define OFFSET(x)
Definition: filter_units.c:230
AVDISCARD_NONE
@ AVDISCARD_NONE
discard nothing
Definition: defs.h:226
AVBSFContext::par_out
AVCodecParameters * par_out
Parameters of the output stream.
Definition: bsf.h:96
FilterUnitsContext::nb_types
int nb_types
Definition: filter_units.c:49
FilterUnitsContext::NOOP
@ NOOP
Definition: filter_units.c:44
CodedBitstreamFragment::units
CodedBitstreamUnit * units
Pointer to an array of units of length nb_units_allocated.
Definition: cbs.h:175
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
CodedBitstreamFragment
Coded bitstream fragment structure, combining one or more units.
Definition: cbs.h:129
FilterUnitsContext::passthrough
bool passthrough
Definition: filter_units.c:50
CodedBitstreamUnitType
uint32_t CodedBitstreamUnitType
The codec-specific type of a bitstream unit.
Definition: cbs.h:54
FilterUnitsContext
Definition: filter_units.c:31
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
AVDISCARD_BIDIR
@ AVDISCARD_BIDIR
discard all bidirectional frames
Definition: defs.h:229
AVDISCARD_ALL
@ AVDISCARD_ALL
discard all
Definition: defs.h:232
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
NULL
#define NULL
Definition: coverity.c:32
FilterUnitsContext::type_list
CodedBitstreamUnitType * type_list
Definition: filter_units.c:48
FFBitStreamFilter
Definition: bsf_internal.h:27
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:242
list
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining list
Definition: filter_design.txt:25
FFBitStreamFilter::p
AVBitStreamFilter p
The public AVBitStreamFilter.
Definition: bsf_internal.h:31
AVDISCARD_NONKEY
@ AVDISCARD_NONKEY
discard all frames except keyframes
Definition: defs.h:231
filter_units_class
static const AVClass filter_units_class
Definition: filter_units.c:274
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:551
filter_units_init
static int filter_units_init(AVBSFContext *bsf)
Definition: filter_units.c:160
AVDISCARD_DEFAULT
@ AVDISCARD_DEFAULT
discard useless packets like 0 size packets in avi
Definition: defs.h:227
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
FilterUnitsContext::discard
int discard
Definition: filter_units.c:40
DISCARD_FLAG_NONE
@ DISCARD_FLAG_NONE
Definition: cbs.h:502
filter_units_filter
static int filter_units_filter(AVBSFContext *bsf, AVPacket *pkt)
Definition: filter_units.c:108
FilterUnitsContext::REMOVE
@ REMOVE
Definition: filter_units.c:46
AVDISCARD_NONINTRA
@ AVDISCARD_NONINTRA
discard all non intra frames
Definition: defs.h:230
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
FilterUnitsContext::mode
enum FilterUnitsContext::@74 mode
FilterUnitsContext::discard_flags
int discard_flags
Definition: filter_units.c:41
AVBSFContext::priv_data
void * priv_data
Opaque filter-specific private data.
Definition: bsf.h:83
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:81
DISCARD_FLAG_KEEP_NON_VCL
@ DISCARD_FLAG_KEEP_NON_VCL
keep non-vcl units even if the picture has been dropped.
Definition: cbs.h:507
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
ff_cbs_all_codec_ids
enum AVCodecID ff_cbs_all_codec_ids[]
Table of all supported codec IDs.
Definition: cbs_bsf.c:25
filter_units_close
static void filter_units_close(AVBSFContext *bsf)
Definition: filter_units.c:220
mem.h
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:57
AVPacket
This structure stores compressed data.
Definition: packet.h:572
filter_units_options
static const AVOption filter_units_options[]
Definition: filter_units.c:232
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AV_OPT_TYPE_FLAGS
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition: opt.h:255
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
ff_bsf_get_packet_ref
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition: bsf.c:256
FilterUnitsContext::fragment
CodedBitstreamFragment fragment
Definition: filter_units.c:35
pkt
static AVPacket * pkt
Definition: demux_decode.c:55
AV_OPT_TYPE_STRING
@ 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:276
AVDISCARD_NONREF
@ AVDISCARD_NONREF
discard all non reference
Definition: defs.h:228
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
CodedBitstreamFragment::nb_units
int nb_units
Number of units in this fragment.
Definition: cbs.h:160
ff_filter_units_bsf
const FFBitStreamFilter ff_filter_units_bsf
Definition: filter_units.c:281