static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; SideDataContext *s = ctx->priv; AVFrameSideData *sd = NULL; if (s->type != -1) sd = av_frame_get_side_data(frame, s->type); switch (s->mode) { case SIDEDATA_SELECT: if (sd) { return ff_filter_frame(outlink, frame); } break; case SIDEDATA_DELETE: if (s->type == -1) { while (frame->nb_side_data) av_frame_remove_side_data(frame, frame->side_data[0]->type); } else if (sd) { av_frame_remove_side_data(frame, s->type); } return ff_filter_frame(outlink, frame); break; default: av_assert0(0); }; av_frame_free(&frame); return 0; }
/* Write a frame to the output */ static int write_frame(AVFilterContext *ctx, FPSContext *s, AVFilterLink *outlink, int *again) { AVFrame *frame; av_assert1(s->frames_count == 2 || (s->status && s->frames_count == 1)); /* We haven't yet determined the pts of the first frame */ if (s->next_pts == AV_NOPTS_VALUE) { if (s->frames[0]->pts != AV_NOPTS_VALUE) { s->next_pts = s->frames[0]->pts; av_log(ctx, AV_LOG_VERBOSE, "Set first pts to %"PRId64"\n", s->next_pts); } else { av_log(ctx, AV_LOG_WARNING, "Discarding initial frame(s) with no " "timestamp.\n"); frame = shift_frame(ctx, s); av_frame_free(&frame); *again = 1; return 0; } } /* There are two conditions where we want to drop a frame: * - If we have two buffered frames and the second frame is acceptable * as the next output frame, then drop the first buffered frame. * - If we have status (EOF) set, drop frames when we hit the * status timestamp. */ if ((s->frames_count == 2 && s->frames[1]->pts <= s->next_pts) || (s->status && s->status_pts <= s->next_pts)) { frame = shift_frame(ctx, s); av_frame_free(&frame); *again = 1; return 0; /* Output a copy of the first buffered frame */ } else { frame = av_frame_clone(s->frames[0]); if (!frame) return AVERROR(ENOMEM); // Make sure Closed Captions will not be duplicated av_frame_remove_side_data(s->frames[0], AV_FRAME_DATA_A53_CC); frame->pts = s->next_pts++; av_log(ctx, AV_LOG_DEBUG, "Writing frame with pts %"PRId64" to pts %"PRId64"\n", s->frames[0]->pts, frame->pts); s->cur_frame_out++; return ff_filter_frame(outlink, frame); } }
static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { VolumeContext *vol = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; int nb_samples = buf->nb_samples; AVFrame *out_buf; AVFrameSideData *sd = av_frame_get_side_data(buf, AV_FRAME_DATA_REPLAYGAIN); int ret; if (sd && vol->replaygain != REPLAYGAIN_IGNORE) { if (vol->replaygain != REPLAYGAIN_DROP) { AVReplayGain *replaygain = (AVReplayGain*)sd->data; int32_t gain = 100000; uint32_t peak = 100000; float g, p; if (vol->replaygain == REPLAYGAIN_TRACK && replaygain->track_gain != INT32_MIN) { gain = replaygain->track_gain; if (replaygain->track_peak != 0) peak = replaygain->track_peak; } else if (replaygain->album_gain != INT32_MIN) { gain = replaygain->album_gain; if (replaygain->album_peak != 0) peak = replaygain->album_peak; } else { av_log(inlink->dst, AV_LOG_WARNING, "Both ReplayGain gain " "values are unknown.\n"); } g = gain / 100000.0f; p = peak / 100000.0f; av_log(inlink->dst, AV_LOG_VERBOSE, "Using gain %f dB from replaygain side data.\n", g); vol->volume = pow(10, (g + vol->replaygain_preamp) / 20); if (vol->replaygain_noclip) vol->volume = FFMIN(vol->volume, 1.0 / p); vol->volume_i = (int)(vol->volume * 256 + 0.5); volume_init(vol); } av_frame_remove_side_data(buf, AV_FRAME_DATA_REPLAYGAIN); } if (vol->volume == 1.0 || vol->volume_i == 256) return ff_filter_frame(outlink, buf); /* do volume scaling in-place if input buffer is writable */ if (av_frame_is_writable(buf)) { out_buf = buf; } else { out_buf = ff_get_audio_buffer(inlink, nb_samples); if (!out_buf) return AVERROR(ENOMEM); ret = av_frame_copy_props(out_buf, buf); if (ret < 0) { av_frame_free(&out_buf); av_frame_free(&buf); return ret; } } if (vol->precision != PRECISION_FIXED || vol->volume_i > 0) { int p, plane_samples; if (av_sample_fmt_is_planar(buf->format)) plane_samples = FFALIGN(nb_samples, vol->samples_align); else plane_samples = FFALIGN(nb_samples * vol->channels, vol->samples_align); if (vol->precision == PRECISION_FIXED) { for (p = 0; p < vol->planes; p++) { vol->scale_samples(out_buf->extended_data[p], buf->extended_data[p], plane_samples, vol->volume_i); } } else if (av_get_packed_sample_fmt(vol->sample_fmt) == AV_SAMPLE_FMT_FLT) { for (p = 0; p < vol->planes; p++) { vol->fdsp.vector_fmul_scalar((float *)out_buf->extended_data[p], (const float *)buf->extended_data[p], vol->volume, plane_samples); } } else { for (p = 0; p < vol->planes; p++) { vol->fdsp.vector_dmul_scalar((double *)out_buf->extended_data[p], (const double *)buf->extended_data[p], vol->volume, plane_samples); } } } emms_c(); if (buf != out_buf) av_frame_free(&buf); return ff_filter_frame(outlink, out_buf); }