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 <stdlib.h>
20 
21 #include "libavutil/mem.h"
22 #include "libavutil/opt.h"
23 
24 #include "bsf.h"
25 #include "bsf_internal.h"
26 #include "cbs.h"
27 
28 
29 typedef struct FilterUnitsContext {
30  const AVClass *class;
31 
34 
35  const char *pass_types;
36  const char *remove_types;
39 
40  enum {
44  } mode;
46  int nb_types;
48 
49 
50 static int filter_units_make_type_list(const char *list_string,
51  CodedBitstreamUnitType **type_list,
52  int *nb_types)
53 {
55  int pass, count;
56 
57  for (pass = 1; pass <= 2; pass++) {
58  long value, range_start, range_end;
59  const char *str;
60  char *value_end;
61 
62  count = 0;
63  for (str = list_string; *str;) {
64  value = strtol(str, &value_end, 0);
65  if (str == value_end)
66  goto invalid;
67  str = (const char *)value_end;
68  if (*str == '-') {
69  ++str;
70  range_start = value;
71  range_end = strtol(str, &value_end, 0);
72  if (str == value_end)
73  goto invalid;
74 
75  for (value = range_start; value < range_end; value++) {
76  if (pass == 2)
77  list[count] = value;
78  ++count;
79  }
80  } else {
81  if (pass == 2)
82  list[count] = value;
83  ++count;
84  }
85  if (*str == '|')
86  ++str;
87  }
88  if (pass == 1) {
89  list = av_malloc_array(count, sizeof(*list));
90  if (!list)
91  return AVERROR(ENOMEM);
92  }
93  }
94 
95  *type_list = list;
96  *nb_types = count;
97  return 0;
98 
99 invalid:
100  av_freep(&list);
101  return AVERROR(EINVAL);
102 }
103 
105 {
107  CodedBitstreamFragment *frag = &ctx->fragment;
108  int err, i, j;
109 
110  err = ff_bsf_get_packet_ref(bsf, pkt);
111  if (err < 0)
112  return err;
113 
114  if (ctx->mode == NOOP && ctx->discard <= AVDISCARD_DEFAULT)
115  return 0;
116 
117  err = ff_cbs_read_packet(ctx->cbc, frag, pkt);
118  if (err < 0) {
119  av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
120  goto fail;
121  }
122 
123  ff_cbs_discard_units(ctx->cbc, frag, ctx->discard, ctx->discard_flags);
124  if (ctx->mode != NOOP) {
125  for (i = frag->nb_units - 1; i >= 0; i--) {
126  for (j = 0; j < ctx->nb_types; j++) {
127  if (frag->units[i].type == ctx->type_list[j])
128  break;
129  }
130  if (ctx->mode == REMOVE ? j < ctx->nb_types
131  : j >= ctx->nb_types)
132  ff_cbs_delete_unit(frag, i);
133  }
134  }
135 
136  if (frag->nb_units == 0) {
137  // Don't return packets with nothing in them.
138  err = AVERROR(EAGAIN);
139  goto fail;
140  }
141 
142  err = ff_cbs_write_packet(ctx->cbc, pkt, frag);
143  if (err < 0) {
144  av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n");
145  goto fail;
146  }
147 
148 fail:
149  if (err < 0)
151  ff_cbs_fragment_reset(frag);
152 
153  return err;
154 }
155 
157 {
159  int err;
160 
161  if (ctx->pass_types && ctx->remove_types) {
162  av_log(bsf, AV_LOG_ERROR, "Exactly one of pass_types or "
163  "remove_types is required.\n");
164  return AVERROR(EINVAL);
165  }
166 
167  if (ctx->pass_types) {
168  ctx->mode = PASS;
169  err = filter_units_make_type_list(ctx->pass_types,
170  &ctx->type_list, &ctx->nb_types);
171  if (err < 0) {
172  av_log(bsf, AV_LOG_ERROR, "Failed to parse pass_types.\n");
173  return err;
174  }
175  } else if (ctx->remove_types) {
176  ctx->mode = REMOVE;
177  err = filter_units_make_type_list(ctx->remove_types,
178  &ctx->type_list, &ctx->nb_types);
179  if (err < 0) {
180  av_log(bsf, AV_LOG_ERROR, "Failed to parse remove_types.\n");
181  return err;
182  }
183  } else if (ctx->discard == AVDISCARD_NONE) {
184  return 0;
185  }
186 
187  err = ff_cbs_init(&ctx->cbc, bsf->par_in->codec_id, bsf);
188  if (err < 0)
189  return err;
190 
191  if (ctx->discard == AVDISCARD_NONE) {
192  // Don't actually decompose anything, we only want the unit data.
193  ctx->cbc->decompose_unit_types = ctx->type_list;
194  ctx->cbc->nb_decompose_unit_types = 0;
195  }
196 
197  if (bsf->par_in->extradata) {
198  CodedBitstreamFragment *frag = &ctx->fragment;
199 
200  err = ff_cbs_read_extradata(ctx->cbc, frag, bsf->par_in);
201  if (err < 0) {
202  av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n");
203  } else {
204  err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, frag);
205  if (err < 0)
206  av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n");
207  }
208 
209  ff_cbs_fragment_reset(frag);
210  }
211 
212  return err;
213 }
214 
216 {
218 
219  av_freep(&ctx->type_list);
220 
221  ff_cbs_fragment_free(&ctx->fragment);
222  ff_cbs_close(&ctx->cbc);
223 }
224 
225 #define OFFSET(x) offsetof(FilterUnitsContext, x)
226 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
227 static const AVOption filter_units_options[] = {
228  { "pass_types", "List of unit types to pass through the filter.",
229  OFFSET(pass_types), AV_OPT_TYPE_STRING,
230  { .str = NULL }, .flags = FLAGS },
231  { "remove_types", "List of unit types to remove in the filter.",
232  OFFSET(remove_types), AV_OPT_TYPE_STRING,
233  { .str = NULL }, .flags = FLAGS },
234 
235  { "discard", "Remove the selected frames",
236  OFFSET(discard), AV_OPT_TYPE_INT,
237  { .i64 = AVDISCARD_NONE }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
238  { "none" , "discard none",
240  { .i64 = AVDISCARD_NONE }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
241  { "default" , "discard none, but can be changed after dynamically",
243  { .i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
244  { "nonref", "discard all non-reference frames",
246  { .i64 = AVDISCARD_NONREF }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
247  { "bidir", "discard all bidirectional frames",
249  { .i64 = AVDISCARD_BIDIR }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
250  { "nonintra", "discard all frames except I frames",
252  { .i64 = AVDISCARD_NONINTRA }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
253  { "nonkey", "discard all frames except keyframes",
255  { .i64 = AVDISCARD_NONKEY }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
256  { "all", "discard all frames",
258  { .i64 = AVDISCARD_ALL }, INT_MIN, INT_MAX, FLAGS, .unit = "discard"},
259 
260  { "discard_flags", "flags to control the discard frame behavior",
261  OFFSET(discard_flags), AV_OPT_TYPE_FLAGS,
262  { .i64 = DISCARD_FLAG_NONE }, INT_MIN, INT_MAX, FLAGS, .unit = "discard_flags"},
263  { "keep_non_vcl", "non-vcl units even if the picture has been dropped",
265  { .i64 = DISCARD_FLAG_KEEP_NON_VCL }, INT_MIN, INT_MAX, FLAGS, .unit = "discard_flags"},
266  { NULL }
267 };
268 
269 static const AVClass filter_units_class = {
270  .class_name = "filter_units",
271  .item_name = av_default_item_name,
272  .option = filter_units_options,
273  .version = LIBAVUTIL_VERSION_INT,
274 };
275 
277  .p.name = "filter_units",
278  .p.codec_ids = ff_cbs_all_codec_ids,
279  .p.priv_class = &filter_units_class,
280  .priv_data_size = sizeof(FilterUnitsContext),
282  .close = &filter_units_close,
284 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:427
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:35
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
FilterUnitsContext::NOOP
@ NOOP
Definition: filter_units.c:41
ff_cbs_fragment_free
av_cold void ff_cbs_fragment_free(CodedBitstreamFragment *frag)
Free the units array of a fragment in addition to what ff_cbs_fragment_reset does.
Definition: cbs.c:186
ff_cbs_read_extradata
int ff_cbs_read_extradata(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, const AVCodecParameters *par)
Read the extradata bitstream found in codec parameters into a fragment, then split into units and dec...
Definition: cbs.c:286
AVBitStreamFilter::name
const char * name
Definition: bsf.h:112
FilterUnitsContext::cbc
CodedBitstreamContext * cbc
Definition: filter_units.c:32
ff_cbs_fragment_reset
void ff_cbs_fragment_reset(CodedBitstreamFragment *frag)
Free the units contained in a fragment as well as the fragment's own data buffer, but not the units a...
Definition: cbs.c:172
DISCARD_FLAG_NONE
@ DISCARD_FLAG_NONE
Definition: cbs.h:502
CodedBitstreamContext
Context structure for coded bitstream operations.
Definition: cbs.h:219
AVOption
AVOption.
Definition: opt.h:346
CodedBitstreamUnit::type
CodedBitstreamUnitType type
Codec-specific type of this unit.
Definition: cbs.h:74
cbs.h
filter
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
Definition: filter_design.txt:228
FilterUnitsContext::remove_types
const char * remove_types
Definition: filter_units.c:36
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:50
AVBSFContext
The bitstream filter state.
Definition: bsf.h:68
ff_cbs_close
av_cold void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
Close a context and free all internal state.
Definition: cbs.c:142
FLAGS
#define FLAGS
Definition: filter_units.c:226
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
bsf.h
fail
#define fail()
Definition: checkasm.h:179
OFFSET
#define OFFSET(x)
Definition: filter_units.c:225
AVDISCARD_NONE
@ AVDISCARD_NONE
discard nothing
Definition: defs.h:213
ff_cbs_write_extradata
int ff_cbs_write_extradata(CodedBitstreamContext *ctx, AVCodecParameters *par, CodedBitstreamFragment *frag)
Write the bitstream of a fragment to the extradata in codec parameters.
Definition: cbs.c:445
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:46
CodedBitstreamFragment::units
CodedBitstreamUnit * units
Pointer to an array of units of length nb_units_allocated.
Definition: cbs.h:168
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
CodedBitstreamFragment
Coded bitstream fragment structure, combining one or more units.
Definition: cbs.h:122
FilterUnitsContext::discard
enum AVDiscard discard
Definition: filter_units.c:37
ff_cbs_write_packet
int ff_cbs_write_packet(CodedBitstreamContext *ctx, AVPacket *pkt, CodedBitstreamFragment *frag)
Write the bitstream of a fragment to a packet.
Definition: cbs.c:474
FilterUnitsContext
Definition: filter_units.c:29
ctx
AVFormatContext * ctx
Definition: movenc.c:49
AVDISCARD_BIDIR
@ AVDISCARD_BIDIR
discard all bidirectional frames
Definition: defs.h:216
AVDISCARD_ALL
@ AVDISCARD_ALL
discard all
Definition: defs.h:219
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
FilterUnitsContext::type_list
CodedBitstreamUnitType * type_list
Definition: filter_units.c:45
FFBitStreamFilter
Definition: bsf_internal.h:27
ff_cbs_all_codec_ids
enum AVCodecID ff_cbs_all_codec_ids[]
Table of all supported codec IDs.
Definition: cbs.c:62
FilterUnitsContext::REMOVE
@ REMOVE
Definition: filter_units.c:43
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
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:218
filter_units_class
static const AVClass filter_units_class
Definition: filter_units.c:269
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:366
filter_units_init
static int filter_units_init(AVBSFContext *bsf)
Definition: filter_units.c:156
AVDISCARD_DEFAULT
@ AVDISCARD_DEFAULT
discard useless packets like 0 size packets in avi
Definition: defs.h:214
ff_cbs_discard_units
void ff_cbs_discard_units(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, enum AVDiscard skip, int flags)
Discard units accroding to 'skip'.
Definition: cbs.c:1061
filter_units_filter
static int filter_units_filter(AVBSFContext *bsf, AVPacket *pkt)
Definition: filter_units.c:104
AVDISCARD_NONINTRA
@ AVDISCARD_NONINTRA
discard all non intra frames
Definition: defs.h:217
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
FilterUnitsContext::mode
enum FilterUnitsContext::@35 mode
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
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::discard_flags
int discard_flags
Definition: filter_units.c:38
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:71
CodedBitstreamUnitType
uint32_t CodedBitstreamUnitType
The codec-specific type of a bitstream unit.
Definition: cbs.h:47
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:235
FilterUnitsContext::PASS
@ PASS
Definition: filter_units.c:42
ff_cbs_read_packet
int ff_cbs_read_packet(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, const AVPacket *pkt)
Read the data bitstream from a packet into a fragment, then split into units and decompose.
Definition: cbs.c:304
filter_units_close
static void filter_units_close(AVBSFContext *bsf)
Definition: filter_units.c:215
mem.h
ff_cbs_init
av_cold int ff_cbs_init(CodedBitstreamContext **ctx_ptr, enum AVCodecID codec_id, void *log_ctx)
Create and initialise a new context for the given codec.
Definition: cbs.c:90
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:501
filter_units_options
static const AVOption filter_units_options[]
Definition: filter_units.c:227
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
AV_OPT_TYPE_FLAGS
@ AV_OPT_TYPE_FLAGS
Definition: opt.h:234
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:33
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:239
AVDiscard
AVDiscard
Definition: defs.h:210
AVDISCARD_NONREF
@ AVDISCARD_NONREF
discard all non reference
Definition: defs.h:215
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:244
CodedBitstreamFragment::nb_units
int nb_units
Number of units in this fragment.
Definition: cbs.h:153
ff_cbs_delete_unit
void ff_cbs_delete_unit(CodedBitstreamFragment *frag, int position)
Delete a unit from a fragment and free all memory it uses.
Definition: cbs.c:860
ff_filter_units_bsf
const FFBitStreamFilter ff_filter_units_bsf
Definition: filter_units.c:276