3204 lines · 101.6 KB · C
RawDownload
/* * ffmpeg filter configuration * * 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 <stdint.h> #include "ffmpeg.h" #include "libavfilter/avfilter.h"#include "libavfilter/buffersink.h"#include "libavfilter/buffersrc.h" #include "libavutil/avassert.h"#include "libavutil/avstring.h"#include "libavutil/bprint.h"#include "libavutil/channel_layout.h"#include "libavutil/downmix_info.h"#include "libavutil/mem.h"#include "libavutil/opt.h"#include "libavutil/pixdesc.h"#include "libavutil/pixfmt.h"#include "libavutil/samplefmt.h"#include "libavutil/time.h"#include "libavutil/timestamp.h" // FIXME private header, used for mid_pred()#include "libavcodec/mathops.h" typedef struct FilterGraphPriv {    FilterGraph      fg;     // name used for logging    char             log_name[32];     int              is_simple;    // true when the filtergraph contains only meta filters    // that do not modify the frame data    int              is_meta;    // source filters are present in the graph    int              have_sources;    int              disable_conversions;     unsigned         nb_outputs_done;     const char      *graph_desc;     char            *nb_threads;     // frame for temporarily holding output from the filtergraph    AVFrame         *frame;    // frame for sending output to the encoder    AVFrame         *frame_enc;     Scheduler       *sch;    unsigned         sch_idx;} FilterGraphPriv; static FilterGraphPriv *fgp_from_fg(FilterGraph *fg){    return (FilterGraphPriv*)fg;} static const FilterGraphPriv *cfgp_from_cfg(const FilterGraph *fg){    return (const FilterGraphPriv*)fg;} // data that is local to the filter thread and not visible outside of ittypedef struct FilterGraphThread {    AVFilterGraph   *graph;     AVFrame         *frame;     // Temporary buffer for output frames, since on filtergraph reset    // we cannot send them to encoders immediately.    // The output index is stored in frame opaque.    AVFifo          *frame_queue_out;     // index of the next input to request from the scheduler    unsigned         next_in;    // set to 1 after at least one frame passed through this output    int              got_frame;     // EOF status of each input/output, as received by the thread    uint8_t         *eof_in;    uint8_t         *eof_out;} FilterGraphThread; typedef struct InputFilterPriv {    InputFilter         ifilter;     InputFilterOptions  opts;     int                 index;     AVFilterContext    *filter;     // used to hold submitted input    AVFrame            *frame;     /* for filters that are not yet bound to an input stream,     * this stores the input linklabel, if any */    uint8_t            *linklabel;     // filter data type    enum AVMediaType    type;    // source data type: AVMEDIA_TYPE_SUBTITLE for sub2video,    // same as type otherwise    enum AVMediaType    type_src;     int                 eof;    int                 bound;     // parameters configured for this input    int                 format;     int                 width, height;    AVRational          sample_aspect_ratio;    enum AVColorSpace   color_space;    enum AVColorRange   color_range;     int                 sample_rate;    AVChannelLayout     ch_layout;     AVRational          time_base;     AVFrameSideData   **side_data;    int                 nb_side_data;     AVFifo             *frame_queue;     AVBufferRef        *hw_frames_ctx;     int                 displaymatrix_present;    int                 displaymatrix_applied;    int32_t             displaymatrix[9];     int                 downmixinfo_present;    AVDownmixInfo       downmixinfo;     struct {        AVFrame *frame;         int64_t last_pts;        int64_t end_pts;         ///< marks if sub2video_update should force an initialization        unsigned int initialize;    } sub2video;} InputFilterPriv; static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter){    return (InputFilterPriv*)ifilter;} typedef struct FPSConvContext {    AVFrame          *last_frame;    /* number of frames emitted by the video-encoding sync code */    int64_t           frame_number;    /* history of nb_frames_prev, i.e. the number of times the     * previous frame was duplicated by vsync code in recent     * do_video_out() calls */    int64_t           frames_prev_hist[3];     uint64_t          dup_warning;     int               last_dropped;    int               dropped_keyframe;     enum VideoSyncMethod vsync_method;     AVRational        framerate;    AVRational        framerate_max;    const AVRational *framerate_supported;    int               framerate_clip;} FPSConvContext; typedef struct OutputFilterPriv {    OutputFilter            ofilter;     int                     index;     void                   *log_parent;    char                    log_name[32];     char                   *name;     AVFilterContext        *filter;     /* desired output stream properties */    int                     format;    int                     width, height;    int                     sample_rate;    AVChannelLayout         ch_layout;    enum AVColorSpace       color_space;    enum AVColorRange       color_range;     AVFrameSideData       **side_data;    int                     nb_side_data;     // time base in which the output is sent to our downstream    // does not need to match the filtersink's timebase    AVRational              tb_out;    // at least one frame with the above timebase was sent    // to our downstream, so it cannot change anymore    int                     tb_out_locked;     AVRational              sample_aspect_ratio;     AVDictionary           *sws_opts;    AVDictionary           *swr_opts;     // those are only set if no format is specified and the encoder gives us multiple options    // They point directly to the relevant lists of the encoder.    const int              *formats;    const AVChannelLayout  *ch_layouts;    const int              *sample_rates;    const enum AVColorSpace *color_spaces;    const enum AVColorRange *color_ranges;     AVRational              enc_timebase;    int64_t                 trim_start_us;    int64_t                 trim_duration_us;    // offset for output timestamps, in AV_TIME_BASE_Q    int64_t                 ts_offset;    int64_t                 next_pts;    FPSConvContext          fps;     unsigned                flags;} OutputFilterPriv; static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter){    return (OutputFilterPriv*)ofilter;} typedef struct FilterCommand {    char *target;    char *command;    char *arg;     double time;    int    all_filters;} FilterCommand; static void filter_command_free(void *opaque, uint8_t *data){    FilterCommand *fc = (FilterCommand*)data;     av_freep(&fc->target);    av_freep(&fc->command);    av_freep(&fc->arg);     av_free(data);} static int sub2video_get_blank_frame(InputFilterPriv *ifp){    AVFrame *frame = ifp->sub2video.frame;    int ret;     av_frame_unref(frame);     frame->width  = ifp->width;    frame->height = ifp->height;    frame->format = ifp->format;    frame->colorspace = ifp->color_space;    frame->color_range = ifp->color_range;     ret = av_frame_get_buffer(frame, 0);    if (ret < 0)        return ret;     memset(frame->data[0], 0, frame->height * frame->linesize[0]);     return 0;} static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h,                                AVSubtitleRect *r){    uint32_t *pal, *dst2;    uint8_t *src, *src2;    int x, y;     if (r->type != SUBTITLE_BITMAP) {        av_log(NULL, AV_LOG_WARNING, "sub2video: non-bitmap subtitle\n");        return;    }    if (r->x < 0 || r->x + r->w > w || r->y < 0 || r->y + r->h > h) {        av_log(NULL, AV_LOG_WARNING, "sub2video: rectangle (%d %d %d %d) overflowing %d %d\n",            r->x, r->y, r->w, r->h, w, h        );        return;    }     dst += r->y * dst_linesize + r->x * 4;    src = r->data[0];    pal = (uint32_t *)r->data[1];    for (y = 0; y < r->h; y++) {        dst2 = (uint32_t *)dst;        src2 = src;        for (x = 0; x < r->w; x++)            *(dst2++) = pal[*(src2++)];        dst += dst_linesize;        src += r->linesize[0];    }} static void sub2video_push_ref(InputFilterPriv *ifp, int64_t pts){    AVFrame *frame = ifp->sub2video.frame;    int ret;     av_assert1(frame->data[0]);    ifp->sub2video.last_pts = frame->pts = pts;    ret = av_buffersrc_add_frame_flags(ifp->filter, frame,                                       AV_BUFFERSRC_FLAG_KEEP_REF |                                       AV_BUFFERSRC_FLAG_PUSH);    if (ret != AVERROR_EOF && ret < 0)        av_log(ifp->ifilter.graph, AV_LOG_WARNING,               "Error while add the frame to buffer source(%s).\n",               av_err2str(ret));} static void sub2video_update(InputFilterPriv *ifp, int64_t heartbeat_pts,                             const AVSubtitle *sub){    AVFrame *frame = ifp->sub2video.frame;    int8_t *dst;    int     dst_linesize;    int num_rects;    int64_t pts, end_pts;     if (sub) {        pts       = av_rescale_q(sub->pts + sub->start_display_time * 1000LL,                                 AV_TIME_BASE_Q, ifp->time_base);        end_pts   = av_rescale_q(sub->pts + sub->end_display_time   * 1000LL,                                 AV_TIME_BASE_Q, ifp->time_base);        num_rects = sub->num_rects;    } else {        /* If we are initializing the system, utilize current heartbeat           PTS as the start time, and show until the following subpicture           is received. Otherwise, utilize the previous subpicture's end time           as the fall-back value. */        pts       = ifp->sub2video.initialize ?                    heartbeat_pts : ifp->sub2video.end_pts;        end_pts   = INT64_MAX;        num_rects = 0;    }    if (sub2video_get_blank_frame(ifp) < 0) {        av_log(ifp->ifilter.graph, AV_LOG_ERROR,               "Impossible to get a blank canvas.\n");        return;    }    dst          = frame->data    [0];    dst_linesize = frame->linesize[0];    for (int i = 0; i < num_rects; i++)        sub2video_copy_rect(dst, dst_linesize, frame->width, frame->height, sub->rects[i]);    sub2video_push_ref(ifp, pts);    ifp->sub2video.end_pts = end_pts;    ifp->sub2video.initialize = 0;} /* Define a function for appending a list of allowed formats * to an AVBPrint. If nonempty, the list will have a header. */#define DEF_CHOOSE_FORMAT(name, type, var, supported_list, none, printf_format, get_name) \static void choose_ ## name (OutputFilterPriv *ofp, AVBPrint *bprint)          \{                                                                              \    if (ofp->var == none && !ofp->supported_list)                              \        return;                                                                \    av_bprintf(bprint, #name "=");                                             \    if (ofp->var != none) {                                                    \        av_bprintf(bprint, printf_format, get_name(ofp->var));                 \    } else {                                                                   \        const type *p;                                                         \                                                                               \        for (p = ofp->supported_list; *p != none; p++) {                       \            av_bprintf(bprint, printf_format "|", get_name(*p));               \        }                                                                      \        if (bprint->len > 0)                                                   \            bprint->str[--bprint->len] = '\0';                                 \    }                                                                          \    av_bprint_chars(bprint, ':', 1);                                           \} DEF_CHOOSE_FORMAT(pix_fmts, enum AVPixelFormat, format, formats,                  AV_PIX_FMT_NONE, "%s", av_get_pix_fmt_name) DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats,                  AV_SAMPLE_FMT_NONE, "%s", av_get_sample_fmt_name) DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0,                  "%d", ) DEF_CHOOSE_FORMAT(color_spaces, enum AVColorSpace, color_space, color_spaces,                  AVCOL_SPC_UNSPECIFIED, "%s", av_color_space_name); DEF_CHOOSE_FORMAT(color_ranges, enum AVColorRange, color_range, color_ranges,                  AVCOL_RANGE_UNSPECIFIED, "%s", av_color_range_name); static void choose_channel_layouts(OutputFilterPriv *ofp, AVBPrint *bprint){    if (av_channel_layout_check(&ofp->ch_layout)) {        av_bprintf(bprint, "channel_layouts=");        av_channel_layout_describe_bprint(&ofp->ch_layout, bprint);    } else if (ofp->ch_layouts) {        const AVChannelLayout *p;         av_bprintf(bprint, "channel_layouts=");        for (p = ofp->ch_layouts; p->nb_channels; p++) {            av_channel_layout_describe_bprint(p, bprint);            av_bprintf(bprint, "|");        }        if (bprint->len > 0)            bprint->str[--bprint->len] = '\0';    } else        return;    av_bprint_chars(bprint, ':', 1);} static int read_binary(void *logctx, const char *path,                       uint8_t **data, int *len){    AVIOContext *io = NULL;    int64_t fsize;    int ret;     *data = NULL;    *len  = 0;     ret = avio_open2(&io, path, AVIO_FLAG_READ, &int_cb, NULL);    if (ret < 0) {        av_log(logctx, AV_LOG_ERROR, "Cannot open file '%s': %s\n",               path, av_err2str(ret));        return ret;    }     fsize = avio_size(io);    if (fsize < 0 || fsize > INT_MAX) {        av_log(logctx, AV_LOG_ERROR, "Cannot obtain size of file %s\n", path);        ret = AVERROR(EIO);        goto fail;    }     *data = av_malloc(fsize);    if (!*data) {        ret = AVERROR(ENOMEM);        goto fail;    }     ret = avio_read(io, *data, fsize);    if (ret != fsize) {        av_log(logctx, AV_LOG_ERROR, "Error reading file %s\n", path);        ret = ret < 0 ? ret : AVERROR(EIO);        goto fail;    }     *len = fsize;     ret = 0;fail:    avio_close(io);    if (ret < 0) {        av_freep(data);        *len = 0;    }    return ret;} static int filter_opt_apply(void *logctx, AVFilterContext *f,                            const char *key, const char *val){    const AVOption *o = NULL;    int ret;     ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN);    if (ret >= 0)        return 0;     if (ret == AVERROR_OPTION_NOT_FOUND && key[0] == '/')        o = av_opt_find(f, key + 1, NULL, 0, AV_OPT_SEARCH_CHILDREN);    if (!o)

Lines 1–500 of 3204.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t