Exemple #1
0
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;
}
Exemple #2
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);
    }
}
Exemple #3
0
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);
}