This patch is analogous to 20f972701806be20a77f808db332d9489343bb78: It hides the internal part of AVBitStreamFilter by adding a new internal structure FFBitStreamFilter (declared in bsf_internal.h) that has an AVBitStreamFilter as its first member; the internal part of AVBitStreamFilter is moved to this new structure. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
		
			
				
	
	
		
			230 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
 | |
|  *
 | |
|  * This file is part of FFmpeg.
 | |
|  *
 | |
|  * FFmpeg is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU Lesser General Public
 | |
|  * License as published by the Free Software Foundation; either
 | |
|  * version 2.1 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * FFmpeg is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  * Lesser General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Lesser General Public
 | |
|  * License along with FFmpeg; if not, write to the Free Software
 | |
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | |
|  */
 | |
| 
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #include "bsf.h"
 | |
| #include "bsf_internal.h"
 | |
| 
 | |
| #include "libavutil/log.h"
 | |
| #include "libavutil/opt.h"
 | |
| #include "libavutil/eval.h"
 | |
| 
 | |
| static const char *const var_names[] = {
 | |
|     "n",                           /// packet index, starting from zero
 | |
|     "tb",                          /// timebase
 | |
|     "pts",                         /// packet presentation timestamp
 | |
|     "dts",                         /// packet decoding timestamp
 | |
|     "nopts",                       /// AV_NOPTS_VALUE
 | |
|     "startpts",                    /// first seen non-AV_NOPTS_VALUE packet timestamp
 | |
|     "startdts",                    /// first seen non-AV_NOPTS_VALUE packet timestamp
 | |
|     "duration", "d",               /// packet duration
 | |
|     "pos",                         /// original position of packet in its source
 | |
|     "size",                        /// packet size
 | |
|     "key" ,                        /// packet keyframe flag
 | |
|     "state",                       /// random-ish state
 | |
|     NULL
 | |
| };
 | |
| 
 | |
| enum var_name {
 | |
|     VAR_N,
 | |
|     VAR_TB,
 | |
|     VAR_PTS,
 | |
|     VAR_DTS,
 | |
|     VAR_NOPTS,
 | |
|     VAR_STARTPTS,
 | |
|     VAR_STARTDTS,
 | |
|     VAR_DURATION, VAR_D,
 | |
|     VAR_POS,
 | |
|     VAR_SIZE,
 | |
|     VAR_KEY,
 | |
|     VAR_STATE,
 | |
|     VAR_VARS_NB
 | |
| };
 | |
| 
 | |
| typedef struct NoiseContext {
 | |
|     const AVClass *class;
 | |
| 
 | |
|     char *amount_str;
 | |
|     char *drop_str;
 | |
|     int dropamount;
 | |
| 
 | |
|     AVExpr *amount_pexpr;
 | |
|     AVExpr *drop_pexpr;
 | |
| 
 | |
|     double var_values[VAR_VARS_NB];
 | |
| 
 | |
|     unsigned int state;
 | |
|     unsigned int pkt_idx;
 | |
| } NoiseContext;
 | |
| 
 | |
| static int noise_init(AVBSFContext *ctx)
 | |
| {
 | |
|     NoiseContext *s = ctx->priv_data;
 | |
|     int ret;
 | |
| 
 | |
|     if (!s->amount_str) {
 | |
|         s->amount_str = (!s->drop_str && !s->dropamount) ? av_strdup("-1") : av_strdup("0");
 | |
|         if (!s->amount_str)
 | |
|             return AVERROR(ENOMEM);
 | |
|     }
 | |
| 
 | |
|     ret = av_expr_parse(&s->amount_pexpr, s->amount_str,
 | |
|                         var_names, NULL, NULL, NULL, NULL, 0, ctx);
 | |
|     if (ret < 0) {
 | |
|         av_log(ctx, AV_LOG_ERROR, "Error in parsing expr for amount: %s\n", s->amount_str);
 | |
|         return ret;
 | |
|     }
 | |
| 
 | |
|     if (s->drop_str && s->dropamount) {
 | |
|         av_log(ctx, AV_LOG_WARNING, "Both drop '%s' and dropamount=%d set. Ignoring dropamount.\n",
 | |
|                s->drop_str, s->dropamount);
 | |
|         s->dropamount = 0;
 | |
|     }
 | |
| 
 | |
|     if (s->drop_str) {
 | |
|         ret = av_expr_parse(&s->drop_pexpr, s->drop_str,
 | |
|                             var_names, NULL, NULL, NULL, NULL, 0, ctx);
 | |
|         if (ret < 0) {
 | |
|             av_log(ctx, AV_LOG_ERROR, "Error in parsing expr for drop: %s\n", s->drop_str);
 | |
|             return ret;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     s->var_values[VAR_TB]       = ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0;
 | |
|     s->var_values[VAR_NOPTS]    = AV_NOPTS_VALUE;
 | |
|     s->var_values[VAR_STARTPTS] = AV_NOPTS_VALUE;
 | |
|     s->var_values[VAR_STARTDTS] = AV_NOPTS_VALUE;
 | |
|     s->var_values[VAR_STATE] = 0;
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static int noise(AVBSFContext *ctx, AVPacket *pkt)
 | |
| {
 | |
|     NoiseContext *s = ctx->priv_data;
 | |
|     int i, ret, amount, drop = 0;
 | |
|     double res;
 | |
| 
 | |
|     ret = ff_bsf_get_packet_ref(ctx, pkt);
 | |
|     if (ret < 0)
 | |
|         return ret;
 | |
| 
 | |
|     s->var_values[VAR_N]           = s->pkt_idx++;
 | |
|     s->var_values[VAR_PTS]         = pkt->pts;
 | |
|     s->var_values[VAR_DTS]         = pkt->dts;
 | |
|     s->var_values[VAR_DURATION]    =
 | |
|     s->var_values[VAR_D]           = pkt->duration;
 | |
|     s->var_values[VAR_SIZE]        = pkt->size;
 | |
|     s->var_values[VAR_KEY]         = !!(pkt->flags & AV_PKT_FLAG_KEY);
 | |
|     s->var_values[VAR_POS]         = pkt->pos;
 | |
| 
 | |
|     if (s->var_values[VAR_STARTPTS] == AV_NOPTS_VALUE)
 | |
|         s->var_values[VAR_STARTPTS] = pkt->pts;
 | |
| 
 | |
|     if (s->var_values[VAR_STARTDTS] == AV_NOPTS_VALUE)
 | |
|         s->var_values[VAR_STARTDTS] = pkt->dts;
 | |
| 
 | |
|     res = av_expr_eval(s->amount_pexpr, s->var_values, NULL);
 | |
| 
 | |
|     if (isnan(res))
 | |
|         amount = 0;
 | |
|     else if (res < 0)
 | |
|         amount = (s->state % 10001 + 1);
 | |
|     else
 | |
|         amount = (int)res;
 | |
| 
 | |
|     if (s->drop_str) {
 | |
|         res = av_expr_eval(s->drop_pexpr, s->var_values, NULL);
 | |
| 
 | |
|         if (isnan(res))
 | |
|             drop = 0;
 | |
|         else if (res < 0)
 | |
|             drop = !(s->state % FFABS((int)res));
 | |
|         else
 | |
|             drop = !!res;
 | |
|     }
 | |
| 
 | |
|     if(s->dropamount) {
 | |
|         drop = !(s->state % s->dropamount);
 | |
|     }
 | |
| 
 | |
|     av_log(ctx, AV_LOG_VERBOSE, "Stream #%d packet %d pts %"PRId64" - amount %d drop %d\n",
 | |
|            pkt->stream_index, (unsigned int)s->var_values[VAR_N], pkt->pts, amount, drop);
 | |
| 
 | |
|     if (drop) {
 | |
|         s->var_values[VAR_STATE] = ++s->state;
 | |
|         av_packet_unref(pkt);
 | |
|         return AVERROR(EAGAIN);
 | |
|     }
 | |
| 
 | |
|     if (amount) {
 | |
|         ret = av_packet_make_writable(pkt);
 | |
|         if (ret < 0) {
 | |
|             av_packet_unref(pkt);
 | |
|             return ret;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < pkt->size; i++) {
 | |
|         s->state += pkt->data[i] + 1;
 | |
|         if (amount && s->state % amount == 0)
 | |
|             pkt->data[i] = s->state;
 | |
|     }
 | |
| 
 | |
|     s->var_values[VAR_STATE] = s->state;
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static void noise_close(AVBSFContext *bsf)
 | |
| {
 | |
|     NoiseContext *s = bsf->priv_data;
 | |
| 
 | |
|     av_expr_free(s->amount_pexpr);
 | |
|     av_expr_free(s->drop_pexpr);
 | |
|     s->amount_pexpr = s->drop_pexpr = NULL;
 | |
| }
 | |
| 
 | |
| #define OFFSET(x) offsetof(NoiseContext, x)
 | |
| #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_BSF_PARAM)
 | |
| static const AVOption options[] = {
 | |
|     { "amount",     NULL, OFFSET(amount_str),     AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
 | |
|     { "drop",       NULL, OFFSET(drop_str),       AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
 | |
|     { "dropamount", NULL, OFFSET(dropamount),     AV_OPT_TYPE_INT,    { .i64 = 0    }, 0, INT_MAX, FLAGS },
 | |
|     { NULL },
 | |
| };
 | |
| 
 | |
| static const AVClass noise_class = {
 | |
|     .class_name = "noise",
 | |
|     .item_name  = av_default_item_name,
 | |
|     .option     = options,
 | |
|     .version    = LIBAVUTIL_VERSION_INT,
 | |
| };
 | |
| 
 | |
| const FFBitStreamFilter ff_noise_bsf = {
 | |
|     .p.name         = "noise",
 | |
|     .p.priv_class   = &noise_class,
 | |
|     .priv_data_size = sizeof(NoiseContext),
 | |
|     .init           = noise_init,
 | |
|     .close          = noise_close,
 | |
|     .filter         = noise,
 | |
| };
 |