1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include <stdlib.h> 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include "bsf.h" 24cabdff1aSopenharmony_ci#include "bsf_internal.h" 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include "libavutil/log.h" 27cabdff1aSopenharmony_ci#include "libavutil/opt.h" 28cabdff1aSopenharmony_ci#include "libavutil/eval.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_cistatic const char *const var_names[] = { 31cabdff1aSopenharmony_ci "n", /// packet index, starting from zero 32cabdff1aSopenharmony_ci "tb", /// timebase 33cabdff1aSopenharmony_ci "pts", /// packet presentation timestamp 34cabdff1aSopenharmony_ci "dts", /// packet decoding timestamp 35cabdff1aSopenharmony_ci "nopts", /// AV_NOPTS_VALUE 36cabdff1aSopenharmony_ci "startpts", /// first seen non-AV_NOPTS_VALUE packet timestamp 37cabdff1aSopenharmony_ci "startdts", /// first seen non-AV_NOPTS_VALUE packet timestamp 38cabdff1aSopenharmony_ci "duration", "d", /// packet duration 39cabdff1aSopenharmony_ci "pos", /// original position of packet in its source 40cabdff1aSopenharmony_ci "size", /// packet size 41cabdff1aSopenharmony_ci "key" , /// packet keyframe flag 42cabdff1aSopenharmony_ci "state", /// random-ish state 43cabdff1aSopenharmony_ci NULL 44cabdff1aSopenharmony_ci}; 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_cienum var_name { 47cabdff1aSopenharmony_ci VAR_N, 48cabdff1aSopenharmony_ci VAR_TB, 49cabdff1aSopenharmony_ci VAR_PTS, 50cabdff1aSopenharmony_ci VAR_DTS, 51cabdff1aSopenharmony_ci VAR_NOPTS, 52cabdff1aSopenharmony_ci VAR_STARTPTS, 53cabdff1aSopenharmony_ci VAR_STARTDTS, 54cabdff1aSopenharmony_ci VAR_DURATION, VAR_D, 55cabdff1aSopenharmony_ci VAR_POS, 56cabdff1aSopenharmony_ci VAR_SIZE, 57cabdff1aSopenharmony_ci VAR_KEY, 58cabdff1aSopenharmony_ci VAR_STATE, 59cabdff1aSopenharmony_ci VAR_VARS_NB 60cabdff1aSopenharmony_ci}; 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_citypedef struct NoiseContext { 63cabdff1aSopenharmony_ci const AVClass *class; 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_ci char *amount_str; 66cabdff1aSopenharmony_ci char *drop_str; 67cabdff1aSopenharmony_ci int dropamount; 68cabdff1aSopenharmony_ci 69cabdff1aSopenharmony_ci AVExpr *amount_pexpr; 70cabdff1aSopenharmony_ci AVExpr *drop_pexpr; 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci double var_values[VAR_VARS_NB]; 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci unsigned int state; 75cabdff1aSopenharmony_ci unsigned int pkt_idx; 76cabdff1aSopenharmony_ci} NoiseContext; 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_cistatic int noise_init(AVBSFContext *ctx) 79cabdff1aSopenharmony_ci{ 80cabdff1aSopenharmony_ci NoiseContext *s = ctx->priv_data; 81cabdff1aSopenharmony_ci int ret; 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci if (!s->amount_str) { 84cabdff1aSopenharmony_ci s->amount_str = (!s->drop_str && !s->dropamount) ? av_strdup("-1") : av_strdup("0"); 85cabdff1aSopenharmony_ci if (!s->amount_str) 86cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 87cabdff1aSopenharmony_ci } 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_ci if (ctx->par_in->codec_id == AV_CODEC_ID_WRAPPED_AVFRAME && 90cabdff1aSopenharmony_ci strcmp(s->amount_str, "0")) { 91cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Wrapped AVFrame noising is unsupported\n"); 92cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 93cabdff1aSopenharmony_ci } 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci ret = av_expr_parse(&s->amount_pexpr, s->amount_str, 96cabdff1aSopenharmony_ci var_names, NULL, NULL, NULL, NULL, 0, ctx); 97cabdff1aSopenharmony_ci if (ret < 0) { 98cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Error in parsing expr for amount: %s\n", s->amount_str); 99cabdff1aSopenharmony_ci return ret; 100cabdff1aSopenharmony_ci } 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci if (s->drop_str && s->dropamount) { 103cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_WARNING, "Both drop '%s' and dropamount=%d set. Ignoring dropamount.\n", 104cabdff1aSopenharmony_ci s->drop_str, s->dropamount); 105cabdff1aSopenharmony_ci s->dropamount = 0; 106cabdff1aSopenharmony_ci } 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci if (s->drop_str) { 109cabdff1aSopenharmony_ci ret = av_expr_parse(&s->drop_pexpr, s->drop_str, 110cabdff1aSopenharmony_ci var_names, NULL, NULL, NULL, NULL, 0, ctx); 111cabdff1aSopenharmony_ci if (ret < 0) { 112cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Error in parsing expr for drop: %s\n", s->drop_str); 113cabdff1aSopenharmony_ci return ret; 114cabdff1aSopenharmony_ci } 115cabdff1aSopenharmony_ci } 116cabdff1aSopenharmony_ci 117cabdff1aSopenharmony_ci s->var_values[VAR_TB] = ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0; 118cabdff1aSopenharmony_ci s->var_values[VAR_NOPTS] = AV_NOPTS_VALUE; 119cabdff1aSopenharmony_ci s->var_values[VAR_STARTPTS] = AV_NOPTS_VALUE; 120cabdff1aSopenharmony_ci s->var_values[VAR_STARTDTS] = AV_NOPTS_VALUE; 121cabdff1aSopenharmony_ci s->var_values[VAR_STATE] = 0; 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_ci return 0; 124cabdff1aSopenharmony_ci} 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_cistatic int noise(AVBSFContext *ctx, AVPacket *pkt) 127cabdff1aSopenharmony_ci{ 128cabdff1aSopenharmony_ci NoiseContext *s = ctx->priv_data; 129cabdff1aSopenharmony_ci int i, ret, amount, drop = 0; 130cabdff1aSopenharmony_ci double res; 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci ret = ff_bsf_get_packet_ref(ctx, pkt); 133cabdff1aSopenharmony_ci if (ret < 0) 134cabdff1aSopenharmony_ci return ret; 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci s->var_values[VAR_N] = s->pkt_idx++; 137cabdff1aSopenharmony_ci s->var_values[VAR_PTS] = pkt->pts; 138cabdff1aSopenharmony_ci s->var_values[VAR_DTS] = pkt->dts; 139cabdff1aSopenharmony_ci s->var_values[VAR_DURATION] = 140cabdff1aSopenharmony_ci s->var_values[VAR_D] = pkt->duration; 141cabdff1aSopenharmony_ci s->var_values[VAR_SIZE] = pkt->size; 142cabdff1aSopenharmony_ci s->var_values[VAR_KEY] = !!(pkt->flags & AV_PKT_FLAG_KEY); 143cabdff1aSopenharmony_ci s->var_values[VAR_POS] = pkt->pos; 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci if (s->var_values[VAR_STARTPTS] == AV_NOPTS_VALUE) 146cabdff1aSopenharmony_ci s->var_values[VAR_STARTPTS] = pkt->pts; 147cabdff1aSopenharmony_ci 148cabdff1aSopenharmony_ci if (s->var_values[VAR_STARTDTS] == AV_NOPTS_VALUE) 149cabdff1aSopenharmony_ci s->var_values[VAR_STARTDTS] = pkt->dts; 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci res = av_expr_eval(s->amount_pexpr, s->var_values, NULL); 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci if (isnan(res)) 154cabdff1aSopenharmony_ci amount = 0; 155cabdff1aSopenharmony_ci else if (res < 0) 156cabdff1aSopenharmony_ci amount = (s->state % 10001 + 1); 157cabdff1aSopenharmony_ci else 158cabdff1aSopenharmony_ci amount = (int)res; 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci if (s->drop_str) { 161cabdff1aSopenharmony_ci res = av_expr_eval(s->drop_pexpr, s->var_values, NULL); 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_ci if (isnan(res)) 164cabdff1aSopenharmony_ci drop = 0; 165cabdff1aSopenharmony_ci else if (res < 0) 166cabdff1aSopenharmony_ci drop = !(s->state % FFABS((int)res)); 167cabdff1aSopenharmony_ci else 168cabdff1aSopenharmony_ci drop = !!res; 169cabdff1aSopenharmony_ci } 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_ci if(s->dropamount) { 172cabdff1aSopenharmony_ci drop = !(s->state % s->dropamount); 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci 175cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_VERBOSE, "Stream #%d packet %d pts %"PRId64" - amount %d drop %d\n", 176cabdff1aSopenharmony_ci pkt->stream_index, (unsigned int)s->var_values[VAR_N], pkt->pts, amount, drop); 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci if (drop) { 179cabdff1aSopenharmony_ci s->var_values[VAR_STATE] = ++s->state; 180cabdff1aSopenharmony_ci av_packet_unref(pkt); 181cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 182cabdff1aSopenharmony_ci } 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci if (amount) { 185cabdff1aSopenharmony_ci ret = av_packet_make_writable(pkt); 186cabdff1aSopenharmony_ci if (ret < 0) { 187cabdff1aSopenharmony_ci av_packet_unref(pkt); 188cabdff1aSopenharmony_ci return ret; 189cabdff1aSopenharmony_ci } 190cabdff1aSopenharmony_ci } 191cabdff1aSopenharmony_ci 192cabdff1aSopenharmony_ci for (i = 0; i < pkt->size; i++) { 193cabdff1aSopenharmony_ci s->state += pkt->data[i] + 1; 194cabdff1aSopenharmony_ci if (amount && s->state % amount == 0) 195cabdff1aSopenharmony_ci pkt->data[i] = s->state; 196cabdff1aSopenharmony_ci } 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_ci s->var_values[VAR_STATE] = s->state; 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci return 0; 201cabdff1aSopenharmony_ci} 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_cistatic void noise_close(AVBSFContext *bsf) 204cabdff1aSopenharmony_ci{ 205cabdff1aSopenharmony_ci NoiseContext *s = bsf->priv_data; 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci av_expr_free(s->amount_pexpr); 208cabdff1aSopenharmony_ci av_expr_free(s->drop_pexpr); 209cabdff1aSopenharmony_ci s->amount_pexpr = s->drop_pexpr = NULL; 210cabdff1aSopenharmony_ci} 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(NoiseContext, x) 213cabdff1aSopenharmony_ci#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_BSF_PARAM) 214cabdff1aSopenharmony_cistatic const AVOption options[] = { 215cabdff1aSopenharmony_ci { "amount", NULL, OFFSET(amount_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, 216cabdff1aSopenharmony_ci { "drop", NULL, OFFSET(drop_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, 217cabdff1aSopenharmony_ci { "dropamount", NULL, OFFSET(dropamount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, 218cabdff1aSopenharmony_ci { NULL }, 219cabdff1aSopenharmony_ci}; 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_cistatic const AVClass noise_class = { 222cabdff1aSopenharmony_ci .class_name = "noise", 223cabdff1aSopenharmony_ci .item_name = av_default_item_name, 224cabdff1aSopenharmony_ci .option = options, 225cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 226cabdff1aSopenharmony_ci}; 227cabdff1aSopenharmony_ci 228cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_noise_bsf = { 229cabdff1aSopenharmony_ci .p.name = "noise", 230cabdff1aSopenharmony_ci .p.priv_class = &noise_class, 231cabdff1aSopenharmony_ci .priv_data_size = sizeof(NoiseContext), 232cabdff1aSopenharmony_ci .init = noise_init, 233cabdff1aSopenharmony_ci .close = noise_close, 234cabdff1aSopenharmony_ci .filter = noise, 235cabdff1aSopenharmony_ci}; 236