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