LCOV - code coverage report
Current view: top level - libavcodec - filter_units_bsf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 109 0.0 %
Date: 2018-05-20 11:54:08 Functions: 0 4 0.0 %

          Line data    Source code
       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/common.h"
      22             : #include "libavutil/opt.h"
      23             : 
      24             : #include "bsf.h"
      25             : #include "cbs.h"
      26             : 
      27             : 
      28             : typedef struct FilterUnitsContext {
      29             :     const AVClass *class;
      30             : 
      31             :     CodedBitstreamContext *cbc;
      32             :     CodedBitstreamFragment fragment;
      33             : 
      34             :     const char *pass_types;
      35             :     const char *remove_types;
      36             : 
      37             :     enum {
      38             :         NOOP,
      39             :         PASS,
      40             :         REMOVE,
      41             :     } mode;
      42             :     CodedBitstreamUnitType *type_list;
      43             :     int nb_types;
      44             : } FilterUnitsContext;
      45             : 
      46             : 
      47           0 : static int filter_units_make_type_list(const char *list_string,
      48             :                                        CodedBitstreamUnitType **type_list,
      49             :                                        int *nb_types)
      50             : {
      51           0 :     CodedBitstreamUnitType *list = NULL;
      52             :     int pass, count;
      53             : 
      54           0 :     for (pass = 1; pass <= 2; pass++) {
      55             :         long value, range_start, range_end;
      56             :         const char *str;
      57             :         char *value_end;
      58             : 
      59           0 :         count = 0;
      60           0 :         for (str = list_string; *str;) {
      61           0 :             value = strtol(str, &value_end, 0);
      62           0 :             if (str == value_end)
      63           0 :                 goto invalid;
      64           0 :             str = (const char *)value_end;
      65           0 :             if (*str == '-') {
      66           0 :                 ++str;
      67           0 :                 range_start = value;
      68           0 :                 range_end   = strtol(str, &value_end, 0);
      69           0 :                 if (str == value_end)
      70           0 :                     goto invalid;
      71             : 
      72           0 :                 for (value = range_start; value < range_end; value++) {
      73           0 :                     if (pass == 2)
      74           0 :                         list[count] = value;
      75           0 :                     ++count;
      76             :                 }
      77             :             } else {
      78           0 :                 if (pass == 2)
      79           0 :                     list[count] = value;
      80           0 :                 ++count;
      81             :             }
      82           0 :             if (*str == '|')
      83           0 :                 ++str;
      84             :         }
      85           0 :         if (pass == 1) {
      86           0 :             list = av_malloc_array(count, sizeof(*list));
      87           0 :             if (!list)
      88           0 :                 return AVERROR(ENOMEM);
      89             :         }
      90             :     }
      91             : 
      92           0 :     *type_list = list;
      93           0 :     *nb_types  = count;
      94           0 :     return 0;
      95             : 
      96           0 : invalid:
      97           0 :     av_freep(&list);
      98           0 :     return AVERROR(EINVAL);
      99             : }
     100             : 
     101           0 : static int filter_units_filter(AVBSFContext *bsf, AVPacket *out)
     102             : {
     103           0 :     FilterUnitsContext      *ctx = bsf->priv_data;
     104           0 :     CodedBitstreamFragment *frag = &ctx->fragment;
     105           0 :     AVPacket *in = NULL;
     106             :     int err, i, j;
     107             : 
     108             :     while (1) {
     109           0 :         err = ff_bsf_get_packet(bsf, &in);
     110           0 :         if (err < 0)
     111           0 :             return err;
     112             : 
     113           0 :         if (ctx->mode == NOOP) {
     114           0 :             av_packet_move_ref(out, in);
     115           0 :             av_packet_free(&in);
     116           0 :             return 0;
     117             :         }
     118             : 
     119           0 :         err = ff_cbs_read_packet(ctx->cbc, frag, in);
     120           0 :         if (err < 0) {
     121           0 :             av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
     122           0 :             goto fail;
     123             :         }
     124             : 
     125           0 :         for (i = 0; i < frag->nb_units; i++) {
     126           0 :             for (j = 0; j < ctx->nb_types; j++) {
     127           0 :                 if (frag->units[i].type == ctx->type_list[j])
     128           0 :                     break;
     129             :             }
     130           0 :             if (ctx->mode == REMOVE ? j <  ctx->nb_types
     131           0 :                                     : j >= ctx->nb_types) {
     132           0 :                 ff_cbs_delete_unit(ctx->cbc, frag, i);
     133           0 :                 --i;
     134             :             }
     135             :         }
     136             : 
     137           0 :         if (frag->nb_units > 0)
     138           0 :             break;
     139             : 
     140             :         // Don't return packets with nothing in them.
     141           0 :         av_packet_free(&in);
     142           0 :         ff_cbs_fragment_uninit(ctx->cbc, frag);
     143             :     }
     144             : 
     145           0 :     err = ff_cbs_write_packet(ctx->cbc, out, frag);
     146           0 :     if (err < 0) {
     147           0 :         av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n");
     148           0 :         goto fail;
     149             :     }
     150             : 
     151           0 :     err = av_packet_copy_props(out, in);
     152           0 :     if (err < 0)
     153           0 :         goto fail;
     154             : 
     155           0 : fail:
     156           0 :     ff_cbs_fragment_uninit(ctx->cbc, frag);
     157           0 :     av_packet_free(&in);
     158             : 
     159           0 :     return err;
     160             : }
     161             : 
     162           0 : static int filter_units_init(AVBSFContext *bsf)
     163             : {
     164           0 :     FilterUnitsContext *ctx = bsf->priv_data;
     165             :     int err;
     166             : 
     167           0 :     if (ctx->pass_types && ctx->remove_types) {
     168           0 :         av_log(bsf, AV_LOG_ERROR, "Exactly one of pass_types or "
     169             :                "remove_types is required.\n");
     170           0 :         return AVERROR(EINVAL);
     171             :     }
     172             : 
     173           0 :     if (ctx->pass_types) {
     174           0 :         ctx->mode = PASS;
     175           0 :         err = filter_units_make_type_list(ctx->pass_types,
     176             :                                           &ctx->type_list, &ctx->nb_types);
     177           0 :         if (err < 0) {
     178           0 :             av_log(bsf, AV_LOG_ERROR, "Failed to parse pass_types.\n");
     179           0 :             return err;
     180             :         }
     181           0 :     } else if (ctx->remove_types) {
     182           0 :         ctx->mode = REMOVE;
     183           0 :         err = filter_units_make_type_list(ctx->remove_types,
     184             :                                           &ctx->type_list, &ctx->nb_types);
     185           0 :         if (err < 0) {
     186           0 :             av_log(bsf, AV_LOG_ERROR, "Failed to parse remove_types.\n");
     187           0 :             return err;
     188             :         }
     189             :     } else {
     190           0 :         return 0;
     191             :     }
     192             : 
     193           0 :     err = ff_cbs_init(&ctx->cbc, bsf->par_in->codec_id, bsf);
     194           0 :     if (err < 0)
     195           0 :         return err;
     196             : 
     197             :     // Don't actually decompose anything, we only want the unit data.
     198           0 :     ctx->cbc->decompose_unit_types    = ctx->type_list;
     199           0 :     ctx->cbc->nb_decompose_unit_types = 0;
     200             : 
     201           0 :     if (bsf->par_in->extradata) {
     202             :         CodedBitstreamFragment ps;
     203             : 
     204           0 :         err = ff_cbs_read_extradata(ctx->cbc, &ps, bsf->par_in);
     205           0 :         if (err < 0) {
     206           0 :             av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n");
     207             :         } else {
     208           0 :             err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, &ps);
     209           0 :             if (err < 0)
     210           0 :                 av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n");
     211             :         }
     212             : 
     213           0 :         ff_cbs_fragment_uninit(ctx->cbc, &ps);
     214             :     }
     215             : 
     216           0 :     return err;
     217             : }
     218             : 
     219           0 : static void filter_units_close(AVBSFContext *bsf)
     220             : {
     221           0 :     FilterUnitsContext *ctx = bsf->priv_data;
     222             : 
     223           0 :     av_freep(&ctx->type_list);
     224             : 
     225           0 :     ff_cbs_close(&ctx->cbc);
     226           0 : }
     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             :     { NULL }
     239             : };
     240             : 
     241             : static const AVClass filter_units_class = {
     242             :     .class_name = "filter_units",
     243             :     .item_name  = av_default_item_name,
     244             :     .option     = filter_units_options,
     245             :     .version    = LIBAVUTIL_VERSION_INT,
     246             : };
     247             : 
     248             : const AVBitStreamFilter ff_filter_units_bsf = {
     249             :     .name           = "filter_units",
     250             :     .priv_data_size = sizeof(FilterUnitsContext),
     251             :     .priv_class     = &filter_units_class,
     252             :     .init           = &filter_units_init,
     253             :     .close          = &filter_units_close,
     254             :     .filter         = &filter_units_filter,
     255             :     .codec_ids      = ff_cbs_all_codec_ids,
     256             : };

Generated by: LCOV version 1.13