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 
29 
30 typedef struct FilterUnitsContext {
31  const AVClass *class;
32 
35 
36  const char *pass_types;
37  const char *remove_types;
38  /* enum AVDiscard, use int for AVOption */
39  int discard;
41 
42  enum {
46  } mode;
48  int nb_types;
51 
52 
53 static int filter_units_make_type_list(const char *list_string,
54  CodedBitstreamUnitType **type_list,
55  int *nb_types)
56 {
58  int pass, count;
59 
60  for (pass = 1; pass <= 2; pass++) {
61  long value, range_start, range_end;
62  const char *str;
63  char *value_end;
64 
65  count = 0;
66  for (str = list_string; *str;) {
67  value = strtol(str, &value_end, 0);
68  if (str == value_end)
69  goto invalid;
70  str = (const char *)value_end;
71  if (*str == '-') {
72  ++str;
73  range_start = value;
74  range_end = strtol(str, &value_end, 0);
75  if (str == value_end)
76  goto invalid;
77 
78  for (value = range_start; value < range_end; value++) {
79  if (pass == 2)
80  list[count] = value;
81  ++count;
82  }
83  } else {
84  if (pass == 2)
85  list[count] = value;
86  ++count;
87  }
88  if (*str == '|')
89  ++str;
90  }
91  if (pass == 1) {
92  list = av_malloc_array(count, sizeof(*list));
93  if (!list)
94  return AVERROR(ENOMEM);
95  }
96  }
97 
98  *type_list = list;
99  *nb_types = count;
100  return 0;
101 
102 invalid:
103  av_freep(&list);
104  return AVERROR(EINVAL);
105 }
106 
108 {
110  CodedBitstreamFragment *frag = &ctx->fragment;
111  int err, i, j;
112 
113  err = ff_bsf_get_packet_ref(bsf, pkt);
114  if (err < 0)
115  return err;
116 
117  if (ctx->passthrough)
118  return 0;
119 
120  err = ff_cbs_read_packet(ctx->cbc, frag, pkt);
121  if (err < 0) {
122  av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
123  goto fail;
124  }
125 
126  ff_cbs_discard_units(ctx->cbc, frag, ctx->discard, ctx->discard_flags);
127  if (ctx->mode != NOOP) {
128  for (i = frag->nb_units - 1; i >= 0; i--) {
129  for (j = 0; j < ctx->nb_types; j++) {
130  if (frag->units[i].type == ctx->type_list[j])
131  break;
132  }
133  if (ctx->mode == REMOVE ? j < ctx->nb_types
134  : j >= ctx->nb_types)
135  ff_cbs_delete_unit(frag, i);
136  }
137  }
138 
139  if (frag->nb_units == 0) {
140  // Don't return packets with nothing in them.
141  err = AVERROR(EAGAIN);
142  goto fail;
143  }
144 
145  err = ff_cbs_write_packet(ctx->cbc, pkt, frag);
146  if (err < 0) {
147  av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n");
148  goto fail;
149  }
150 
151 fail:
152  if (err < 0)
154  ff_cbs_fragment_reset(frag);
155 
156  return err;
157 }
158 
160 {
162  int err;
163 
164  if (ctx->pass_types && ctx->remove_types) {
165  av_log(bsf, AV_LOG_ERROR, "Exactly one of pass_types or "
166  "remove_types is required.\n");
167  return AVERROR(EINVAL);
168  }
169 
170  if (ctx->pass_types) {
171  ctx->mode = PASS;
172  err = filter_units_make_type_list(ctx->pass_types,
173  &ctx->type_list, &ctx->nb_types);
174  if (err < 0) {
175  av_log(bsf, AV_LOG_ERROR, "Failed to parse pass_types.\n");
176  return err;
177  }
178  } else if (ctx->remove_types) {
179  ctx->mode = REMOVE;
180  err = filter_units_make_type_list(ctx->remove_types,
181  &ctx->type_list, &ctx->nb_types);
182  if (err < 0) {
183  av_log(bsf, AV_LOG_ERROR, "Failed to parse remove_types.\n");
184  return err;
185  }
186  } else if (ctx->discard == AVDISCARD_NONE) {
187  ctx->passthrough = true;
188  return 0;
189  }
190 
191  err = ff_cbs_init(&ctx->cbc, bsf->par_in->codec_id, bsf);
192  if (err < 0)
193  return err;
194 
195  if (ctx->discard == AVDISCARD_NONE) {
196  // Don't actually decompose anything, we only want the unit data.
197  ctx->cbc->decompose_unit_types = ctx->type_list;
198  ctx->cbc->nb_decompose_unit_types = 0;
199  }
200 
201  if (bsf->par_in->extradata) {
202  CodedBitstreamFragment *frag = &ctx->fragment;
203 
204  err = ff_cbs_read_extradata(ctx->cbc, frag, bsf->par_in);
205  if (err < 0) {
206  av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n");
207  } else {
208  err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, frag);
209  if (err < 0)
210  av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n");
211  }
212 
213  ff_cbs_fragment_reset(frag);
214  }
215 
216  return err;
217 }
218 
220 {
222 
223  av_freep(&ctx->type_list);
224 
225  ff_cbs_fragment_free(&ctx->fragment);
226  ff_cbs_close(&ctx->cbc);
227 }
228 
229 #define OFFSET(x) offsetof(FilterUnitsContext, x)
230 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
231 static const AVOption filter_units_options[] = {
232  { "pass_types", "List of unit types to pass through the filter.",
233  OFFSET(pass_types), AV_OPT_TYPE_STRING,
234  { .str = NULL }, .flags = FLAGS },
235  { "remove_types", "List of unit types to remove in the filter.",
236  OFFSET(remove_types), AV_OPT_TYPE_STRING,
237  { .str = NULL }, .flags = FLAGS },
238 
239  { "discard", "Remove the selected frames",
240  OFFSET(discard), AV_OPT_TYPE_INT,
241  { .i64 = AVDISCARD_NONE }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
242  { "none" , "discard none",
244  { .i64 = AVDISCARD_NONE }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
245  { "default" , "discard none, but can be changed after dynamically",
247  { .i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
248  { "nonref", "discard all non-reference frames",
250  { .i64 = AVDISCARD_NONREF }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
251  { "bidir", "discard all bidirectional frames",
253  { .i64 = AVDISCARD_BIDIR }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
254  { "nonintra", "discard all frames except I frames",
256  { .i64 = AVDISCARD_NONINTRA }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
257  { "nonkey", "discard all frames except keyframes",
259  { .i64 = AVDISCARD_NONKEY }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
260  { "all", "discard all frames",
262  { .i64 = AVDISCARD_ALL }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
263 
264  { "discard_flags", "flags to control the discard frame behavior",
265  OFFSET(discard_flags), AV_OPT_TYPE_FLAGS,
266  { .i64 = DISCARD_FLAG_NONE }, INT_MIN, INT_MAX, FLAGS, .unit = "discard_flags"},
267  { "keep_non_vcl", "non-vcl units even if the picture has been dropped",
269  { .i64 = DISCARD_FLAG_KEEP_NON_VCL }, INT_MIN, INT_MAX, FLAGS, .unit = "discard_flags"},
270  { NULL }
271 };
272 
273 static const AVClass filter_units_class = {
274  .class_name = "filter_units",
275  .item_name = av_default_item_name,
276  .option = filter_units_options,
277  .version = LIBAVUTIL_VERSION_INT,
278 };
279 
281  .p.name = "filter_units",
282  .p.codec_ids = ff_cbs_all_codec_ids,
283  .p.priv_class = &filter_units_class,
284  .priv_data_size = sizeof(FilterUnitsContext),
288 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:432
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:69
FilterUnitsContext::pass_types
const char * pass_types
Definition: filter_units.c:36
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:33
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:44
FilterUnitsContext::remove_types
const char * remove_types
Definition: filter_units.c:37
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:53
AVBSFContext
The bitstream filter state.
Definition: bsf.h:68
FLAGS
#define FLAGS
Definition: filter_units.c:230
close
static av_cold void close(AVCodecParserContext *s)
Definition: apv_parser.c:197
bsf.h
fail
#define fail()
Definition: checkasm.h:219
OFFSET
#define OFFSET(x)
Definition: filter_units.c:229
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:48
FilterUnitsContext::NOOP
@ NOOP
Definition: filter_units.c:43
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:49
CodedBitstreamUnitType
uint32_t CodedBitstreamUnitType
The codec-specific type of a bitstream unit.
Definition: cbs.h:54
FilterUnitsContext
Definition: filter_units.c:30
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:47
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:273
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:550
filter_units_init
static int filter_units_init(AVBSFContext *bsf)
Definition: filter_units.c:159
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:39
DISCARD_FLAG_NONE
@ DISCARD_FLAG_NONE
Definition: cbs.h:510
filter_units_filter
static int filter_units_filter(AVBSFContext *bsf, AVPacket *pkt)
Definition: filter_units.c:107
FilterUnitsContext::REMOVE
@ REMOVE
Definition: filter_units.c:45
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:40
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:515
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
filter_units_close
static void filter_units_close(AVBSFContext *bsf)
Definition: filter_units.c:219
mem.h
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
AVPacket
This structure stores compressed data.
Definition: packet.h:565
filter_units_options
static const AVOption filter_units_options[]
Definition: filter_units.c:231
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:34
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:280