ffmpeg给视频加水印

学习如何使用ffmpeg的编程主要是熟悉API(当然可以研究它的源码,分析他的架构和如何实现的编码是更有价值的)。这里主要将程序里的函数提出来分析。

1 avfilter_get_by_name()

根据filter的名字获取到AVFilter


/**
 * Get a filter definition matching the given name.
 *
 * @param name the filter name to find
 * @return     the filter definition, if any matching one is registered.
 *             NULL if none found.
 */
#if !FF_API_NOCONST_GET_NAME
const
#endif
AVFilter *avfilter_get_by_name(const char *name);


2 avfilter_inout_alloc()

分配一个AVFilterInOut入口


/**
 * Allocate a single AVFilterInOut entry.
 * Must be freed with avfilter_inout_free().
 * @return allocated AVFilterInOut on success, NULL on failure.
 */
AVFilterInOut *avfilter_inout_alloc(void);
AVFilterInOut是什么?

一个输入或者输出的过滤器链的链表节点。


/**
 * A linked-list of the inputs/outputs of the filter chain.
 *
 * This is mainly useful for avfilter_graph_parse() / avfilter_graph_parse2(),
 * where it is used to communicate open (unlinked) inputs and outputs from and
 * to the caller.
 * This struct specifies, per each not connected pad contained in the graph, the
 * filter context and the pad index required for establishing a link.
 */
typedef struct AVFilterInOut {
    /** unique name for this input/output in the list */
    char *name;

    /** filter context associated to this input/output */
    AVFilterContext *filter_ctx;

    /** index of the filt_ctx pad to use for linking */
    int pad_idx;

    /** next input/input in the list, NULL if this is the last */
    struct AVFilterInOut *next;
} AVFilterInOut;


3 avfilter_graph_allc()

分配一个AVFilterGraph的空间


/**
 * Allocate a filter graph.
 */
AVFilterGraph *avfilter_graph_alloc(void);
那么AVFilterGraph是什么?反正Filter是用FlterGraph组织管理的。



typedef struct AVFilterGraph {
    const AVClass *av_class;
#if FF_API_FOO_COUNT
    attribute_deprecated
    unsigned filter_count_unused;
#endif
    AVFilterContext **filters;
#if !FF_API_FOO_COUNT
    unsigned nb_filters;
#endif

    char *scale_sws_opts; ///< sws options to use for the auto-inserted scale filters
    char *resample_lavr_opts;   ///< libavresample options to use for the auto-inserted resample filters
#if FF_API_FOO_COUNT
    unsigned nb_filters;
#endif

    /**
     * Type of multithreading allowed for filters in this graph. A combination
     * of AVFILTER_THREAD_* flags.
     *
     * May be set by the caller at any point, the setting will apply to all
     * filters initialized after that. The default is allowing everything.
     *
     * When a filter in this graph is initialized, this field is combined using
     * bit AND with AVFilterContext.thread_type to get the final mask used for
     * determining allowed threading types. I.e. a threading type needs to be
     * set in both to be allowed.
     */
    int thread_type;
/**
     * Maximum number of threads used by filters in this graph. May be set by
     * the caller before adding any filters to the filtergraph. Zero (the
     * default) means that the number of threads is determined automatically.
     */
    int nb_threads;

    /**
     * Opaque object for libavfilter internal use.
     */
    AVFilterGraphInternal *internal;

    /**
     * Opaque user data. May be set by the caller to an arbitrary value, e.g. to
     * be used from callbacks like @ref AVFilterGraph.execute.
     * Libavfilter will not touch this field in any way.
     */
    void *opaque;

    /**
     * This callback may be set by the caller immediately after allocating the
     * graph and before adding any filters to it, to provide a custom
     * multithreading implementation.
     *
     * If set, filters with slice threading capability will call this callback
     * to execute multiple jobs in parallel.
     *
     * If this field is left unset, libavfilter will use its internal
     * implementation, which may or may not be multithreaded depending on the
     * platform and build options.
     */
    avfilter_execute_func *execute;
char *aresample_swr_opts; ///< swr options to use for the auto-inserted aresample filters, Access ONLY through AVOptions

    /**
     * Private fields
     *
     * The following fields are for internal use only.
     * Their type, offset, number and semantic can change without notice.
     */

    AVFilterLink **sink_links;
    int sink_links_count;

    unsigned disable_auto_convert;
} AVFilterGraph;


4 avfiter_graph_alloc_filter()

在filtergraph里创建一个filter实例。


/**
 * Create a new filter instance in a filter graph.
 *
 * @param graph graph in which the new filter will be used
 * @param filter the filter to create an instance of
 * @param name Name to give to the new instance (will be copied to
 *             AVFilterContext.name). This may be used by the caller to identify
 *             different filters, libavfilter itself assigns no semantics to
 *             this parameter. May be NULL.
 *
 * @return the context of the newly created filter instance (note that it is
 *         also retrievable directly through AVFilterGraph.filters or with
 *         avfilter_graph_get_filter()) on success or NULL on failure.
 */
AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph,
                                             const AVFilter *filter,
                                             const char *name);


5 avfilter_graph_create_filter()

创建并添加一个filter实例到一个已经存在的graph中。


/**
 * Create and add a filter instance into an existing graph.
 * The filter instance is created from the filter filt and inited
 * with the parameters args and opaque.
 *
 * In case of success put in *filt_ctx the pointer to the created
 * filter instance, otherwise set *filt_ctx to NULL.
 *
 * @param name the instance name to give to the created filter instance
 * @param graph_ctx the filter graph
 * @return a negative AVERROR error code in case of failure, a non
 * negative value otherwise
 */
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,
                                 const char *name, const char *args, void *opaque,
                                 AVFilterGraph *graph_ctx);

6 av_buffersink_params_alloc()

创建一个AVBufferSinkParams结构体。必须用av_free()函数来释放。


/**
 * Create an AVBufferSinkParams structure.
 *
 * Must be freed with av_free().
 */
AVBufferSinkParams *av_buffersink_params_alloc(void);
那么什么是AVBufferSinkParams结构体呢?用于初始化一个buffersink上下文的结构体。


/**
 * Struct to use for initializing a buffersink context.
 */
typedef struct {
    const enum AVPixelFormat *pixel_fmts; ///< list of allowed pixel formats, terminated by AV_PIX_FMT_NONE
} AVBufferSinkParams;

7 avfilter_graph_parse_ptr()

添加一个用字符串描述的graph到一个graph中。


/**
 * Add a graph described by a string to a graph.
 *
 * @param graph   the filter graph where to link the parsed graph context
 * @param filters string to be parsed
 * @param inputs  pointer to a linked list to the inputs of the graph, may be NULL.
 *                If non-NULL, *inputs is updated to contain the list of open inputs
 *                after the parsing, should be freed with avfilter_inout_free().
 * @param outputs pointer to a linked list to the outputs of the graph, may be NULL.
 *                If non-NULL, *outputs is updated to contain the list of open outputs
 *                after the parsing, should be freed with avfilter_inout_free().
 * @return non negative on success, a negative AVERROR code on error
 */
int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters,
                             AVFilterInOut **inputs, AVFilterInOut **outputs,
                             void *log_ctx);

8 avfilter_graph_config()

检查有效性并配置graph中所有的links和格式。


/**
 * Check validity and configure all the links and formats in the graph.
 *
 * @param graphctx the filter graph
 * @param log_ctx context used for logging
 * @return >= 0 in case of success, a negative AVERROR code otherwise
 */
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx);

9 avfilter_graph_free()

释放一个graph,并销毁他的links,并将指向AVFilterGraph的指针设为NULL。如果本来就是NULL,什么也不干

/**
 * Free a graph, destroy its links, and set *graph to NULL.
 * If *graph is NULL, do nothing.
 */
void avfilter_graph_free(AVFilterGraph **graph);

10 avcodec_get_frame_defaults()

将指定的AVFrame的所有字段设为默认值。


/**
 * Set the fields of the given AVFrame to default values.
 *
 * @param frame The AVFrame of which the fields should be set to default values.
 *
 * @deprecated use av_frame_unref()
 */
attribute_deprecated
void avcodec_get_frame_defaults(AVFrame *frame);

11 av_frame_get_best_effort_timestamp()

获取AVFrame里的timestamp字段。


int64_t av_frame_get_best_effort_timestamp(const AVFrame *frame);

12 av_buffersrc_add_frame()

添加一帧到缓冲源


/**
 * Add a frame to the buffer source.
 *
 * @param ctx   an instance of the buffersrc filter
 * @param frame frame to be added. If the frame is reference counted, this
 * function will take ownership of the reference(s) and reset the frame.
 * Otherwise the frame data will be copied. If this function returns an error,
 * the input frame is not touched.
 *
 * @return 0 on success, a negative AVERROR on error.
 *
 * @note the difference between this function and av_buffersrc_write_frame() is
 * that av_buffersrc_write_frame() creates a new reference to the input frame,
 * while this function takes ownership of the reference passed to it.
 *
 * This function is equivalent to av_buffersrc_add_frame_flags() without the
 * AV_BUFFERSRC_FLAG_KEEP_REF flag.
 */
int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame);

13 av_buffersink_get_buffer_ref()

这个函数从buffer_sink参数中获取音或者视频缓冲数据并放到bufref参数(AVFilterBufferRef结构体指针)中去。


/**
 * Get an audio/video buffer data from buffer_sink and put it in bufref.
 *
 * This function works with both audio and video buffer sinks.
 *  
 * @param buffer_sink pointer to a buffersink or abuffersink context
 * @param flags a combination of AV_BUFFERSINK_FLAG_* flags
 * @return >= 0 in case of success, a negative AVERROR code in case of
 * failure
 */ 
attribute_deprecated
int av_buffersink_get_buffer_ref(AVFilterContext *buffer_sink,
                                 AVFilterBufferRef **bufref, int flags);
AVFilterBufferRef结构体是什么?是一个AVFilterBuffer结构的参考。因为每一个过滤器为了不使用memcpy而进行图像裁剪,可以操作buffer的原始版本,因此,缓冲区origin以及尺寸是属于每个引用的属性。


/**
 * A reference to an AVFilterBuffer. Since filters can manipulate the origin of
 * a buffer to, for example, crop image without any memcpy, the buffer origin
 * and dimensions are per-reference properties. Linesize is also useful for
 * image flipping, frame to field filters, etc, and so is also per-reference.
 *
 * TODO: add anything necessary for frame reordering
 */
typedef struct AVFilterBufferRef {
    AVFilterBuffer *buf;        ///< the buffer that this is a reference to
    uint8_t *data[8];           ///< picture/audio data for each plane
    /**  
     * pointers to the data planes/channels.
     *
     * For video, this should simply point to data[].
     *
     * For planar audio, each channel has a separate data pointer, and
     * linesize[0] contains the size of each channel buffer.
     * For packed audio, there is just one data pointer, and linesize[0]
     * contains the total size of the buffer for all channels.
     *
     * Note: Both data and extended_data will always be set, but for planar
     * audio with more channels that can fit in data, extended_data must be used
     * in order to access all channels.
     */
    uint8_t **extended_data;
    int linesize[8];            ///< number of bytes per line

    AVFilterBufferRefVideoProps *video; ///< video buffer specific properties
    AVFilterBufferRefAudioProps *audio; ///< audio buffer specific properties
 /**
     * presentation timestamp. The time unit may change during
     * filtering, as it is specified in the link and the filter code
     * may need to rescale the PTS accordingly.
     */
    int64_t pts;
    int64_t pos;                ///< byte position in stream, -1 if unknown

    int format;                 ///< media format

    int perms;                  ///< permissions, see the AV_PERM_* flags

    enum AVMediaType type;      ///< media type of buffer data

    AVDictionary *metadata;     ///< dictionary containing metadata key=value tags
} AVFilterBufferRef;
AVFilterBuffer又是什么?是一个用于滤镜系统的参考计数的缓冲区数据类型。filter不要存储直接指向这个结构体的指针,而要使用上面那个AVFilterBufferRef结构体。


/**
 * A reference-counted buffer data type used by the filter system. Filters
 * should not store pointers to this structure directly, but instead use the
 * AVFilterBufferRef structure below.
 */
typedef struct AVFilterBuffer {
    uint8_t *data[8];           ///< buffer data for each plane/channel

    /**
     * pointers to the data planes/channels.
     *
     * For video, this should simply point to data[].
     *
     * For planar audio, each channel has a separate data pointer, and
     * linesize[0] contains the size of each channel buffer.
     * For packed audio, there is just one data pointer, and linesize[0]
     * contains the total size of the buffer for all channels.
     *
     * Note: Both data and extended_data will always be set, but for planar
     * audio with more channels that can fit in data, extended_data must be used
     * in order to access all channels.
     */
    uint8_t **extended_data;
    int linesize[8];            ///< number of bytes per line

    /** private data to be used by a custom free function */
    void *priv;
    /**
     * A pointer to the function to deallocate this buffer if the default
     * function is not sufficient. This could, for example, add the memory
     * back into a memory pool to be reused later without the overhead of
     * reallocating it from scratch.
*/
    void (*free)(struct AVFilterBuffer *buf);

    int format;                 ///< media format
    int w, h;                   ///< width and height of the allocated buffer
    unsigned refcount;          ///< number of references to this buffer
} AVFilterBuffer;

14 avfilter_unref_bufferp()

删除对一个AVFilterBuffer的引用,并将指针设为NULL。如果这是最后一个引用,那么AVFilterBuffer结构体自己会自动删除。


/**                 
 * Remove a reference to a buffer and set the pointer to NULL.
 * If this is the last reference to the buffer, the buffer itself
 * is also automatically freed.
 *                                          
 * @param ref pointer to the buffer reference
 */
attribute_deprecated
void avfilter_unref_bufferp(AVFilterBufferRef **ref);

 15 例子中用到的两种Filter

15.1 buffer的文档

buffer是一种源filter,类似于DirectShow里面也是那种源filter。

Buffer video frames, and make them available to the filter chain.

This source is mainly intended for a programmatic use, in particular through the interface defined in ‘libavfilter/vsrc_buffer.h’.

It accepts the following parameters:(他的主要参数如下)

‘video_size’

Specify the size (width and height) of the buffered video frames. For the syntax of this option, check the "Video size" section in the ffmpeg-utils manual.

‘width’

The input video width.

‘height’

The input video height.

‘pix_fmt’

A string representing the pixel format of the buffered video frames. It may be a number corresponding to a pixel format, or a pixel format name.

‘time_base’

Specify the timebase assumed by the timestamps of the buffered frames.

‘frame_rate’

Specify the frame rate expected for the video stream.

‘pixel_aspect, sar’

The sample (pixel) aspect ratio of the input video.

‘sws_param’

Specify the optional parameters to be used for the scale filter which is automatically inserted when an input change is detected in the input size or format.

For example:

 
buffer=width=320:height=240:pix_fmt=yuv410p:time_base=1/24:sar=1

will instruct the source to accept video frames with size 320x240 and with format "yuv410p", assuming 1/24 as the timestamps timebase and square pixels (1:1 sample aspect ratio). Since the pixel format with name "yuv410p" corresponds to the number 6 (check the enum AVPixelFormat definition in ‘libavutil/pixfmt.h’), this example corresponds to:

 
buffer=size=320x240:pixfmt=6:time_base=1/24:pixel_aspect=1/1

Alternatively, the options can be specified as a flat string, but this syntax is deprecated:

width:height:pix_fmt:time_base.num:time_base.den:pixel_aspect.num:pixel_aspect.den[:sws_param]

15.2 buffersink的文档

buffersink是一种sink过滤器。也就是用在最后的那种过滤器。

Buffer video frames, and make them available to the end of the filter graph.

This sink is mainly intended for programmatic use, in particular through the interface defined in ‘libavfilter/buffersink.h’ or the options system.

It accepts a pointer to an AVBufferSinkContext structure, which defines the incoming buffers’ formats, to be passed as the opaque parameter toavfilter_init_filterfor initialization.













你可能感兴趣的:(ffmpeg给视频加水印)