ffmpeg实现视频实时动态时间水印

mac2025-10-11  9

https://blog.csdn.net/bixinwei22/article/details/94454258

首先看下效果

左上角的实时当前时间,纯c完成。下面的是hello ffmpeg字样是avfilter的drawtext实现。

动态时间水印,其实ffmpeg有命令可以实现,不过我在windows下发现用不了,而且转换出来的图片会质量变差。

所以想着自己用C去实现。上面的2019-07-02 16:30:46 这些是在android下,用canvas drawtext每一个字符,然后生产对应的

bitmap,然后从bitmap里面提取出rgb数据,然后转出来yuv的y数据,因为我们只需要黑白两种颜色,所以使用y足够了。

avfilter我的博客还没有讲过,以后有时间再讲。

下面上代码

#include <stdio.h> #include <stdlib.h> #include <string> #include <iostream> extern "C" {   #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" #include "libswresample/swresample.h" #include "libavutil/time.h" #include "libswresample/swresample.h" #include "libavutil/audio_fifo.h" #include "libavutil/avutil.h" #include "libavutil/opt.h" #include "libavfilter/avfilter.h" #include "libavfilter/avfiltergraph.h" #include "libavfilter/buffersink.h" #include "libavfilter/buffersrc.h" } using namespace std; void Init() {     av_register_all();     avfilter_register_all();     avformat_network_init();     //av_log_set_level(AV_LOG_ERROR); }   AVFilterGraph * filter_graph = nullptr; AVFilterContext *buffersink_ctx = nullptr;; AVFilterContext *buffersrc_ctx = nullptr;;   AVFormatContext * ifmt_ctx = NULL; AVFormatContext * ofmt_ctx = NULL; AVStream *ist_v = NULL; AVCodecContext * ic_ctx_v = NULL; int iv_index = -1; AVStream *ost_v = NULL; AVCodecContext * oc_ctx_v = NULL;   char *mNumArrays; int  num_width = 17; int  num_height = 23; int off_x = 18; int off_y = 18; int patternLen; int getIndex(char c) {     if (c >= '0' && c <= '9')         return c - '0';     else if (c == '-')         return 10;     else if (c == ' ')         return 11;     else if (c == ':')         return 12;     return 11; } void initWatemake() {          char pattern[] = "yyyy-MM-dd HH:mm:ss";     patternLen = sizeof(pattern);     mNumArrays = (char*)malloc(num_width * num_height*patternLen);     char NUM_0[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_1[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_2[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_3[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_4[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_5[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_6[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_7[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_8[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_9[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_SPACE[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_COLON[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     char NUM_LINE[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };     int size = num_width * num_height;     memcpy(mNumArrays, NUM_0, size);     memcpy(mNumArrays + size * 1, NUM_1, size);     memcpy(mNumArrays + size * 2, NUM_2, size);     memcpy(mNumArrays + size * 3, NUM_3, size);     memcpy(mNumArrays + size * 4, NUM_4, size);     memcpy(mNumArrays + size * 5, NUM_5, size);     memcpy(mNumArrays + size * 6, NUM_6, size);     memcpy(mNumArrays + size * 7, NUM_7, size);     memcpy(mNumArrays + size * 8, NUM_8, size);     memcpy(mNumArrays + size * 9, NUM_9, size);     memcpy(mNumArrays + size * 10, NUM_LINE, size);     memcpy(mNumArrays + size * 11, NUM_SPACE, size);     memcpy(mNumArrays + size * 12, NUM_COLON, size); }   int InitDecodeCodec(AVCodecID codecId) {     auto codec = avcodec_find_decoder(codecId);     if (!codec)     {         return -1;     }       if (codec->capabilities & CODEC_CAP_TRUNCATED)         ic_ctx_v->flags |= CODEC_FLAG_TRUNCATED;     int ret = avcodec_open2(ic_ctx_v, codec, NULL);     if (ret < 0) {         cout << "open input vcodec failed" << endl;     }     return ret;   }   int OpenInput(char *filename) {     ifmt_ctx = avformat_alloc_context();         int ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL);     if (ret < 0)     {         return  ret;     }     ret = avformat_find_stream_info(ifmt_ctx, NULL);     av_dump_format(ifmt_ctx, 0, filename, 0);     if (ret >= 0)     {         cout << "open input stream successfully" << endl;     }     for (int i = 0; i < ifmt_ctx->nb_streams; i++) {         if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {             iv_index = i;             ist_v = ifmt_ctx->streams[i];             ic_ctx_v = ist_v->codec;         }       }     InitDecodeCodec(ic_ctx_v->codec_id);     return ret; }       int InitEncoderCodec(int dstW, int dstH) {     AVCodec *  pH264Codec = avcodec_find_encoder(AV_CODEC_ID_H264);     if (NULL == pH264Codec)     {         cout << "find output vcodec failed" << endl;         return  -1;     }     oc_ctx_v = avcodec_alloc_context3(pH264Codec);     oc_ctx_v->gop_size = ic_ctx_v->gop_size;     oc_ctx_v->has_b_frames = 0;     oc_ctx_v->max_b_frames = 0;     oc_ctx_v->codec_id = pH264Codec->id;     oc_ctx_v->time_base.num = ic_ctx_v->time_base.num;;     oc_ctx_v->time_base.den = ic_ctx_v->time_base.den;;     oc_ctx_v->pix_fmt = *pH264Codec->pix_fmts;     oc_ctx_v->width = dstW;     oc_ctx_v->height = dstH;       oc_ctx_v->codec_tag = 0;     // some formats want stream headers to be separate     if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)         oc_ctx_v->flags |= CODEC_FLAG_GLOBAL_HEADER;       int ret = avcodec_open2(oc_ctx_v, pH264Codec, NULL);     if (ret < 0)     {         cout << "open output vcodec failed" << endl;         return  ret;     }     ost_v = avformat_new_stream(ofmt_ctx, oc_ctx_v->codec);     ost_v->codec = oc_ctx_v;       return 1; }       int OpenOutput(char *fileName) {     int ret = 0;     ret = avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", fileName);     if (ret < 0)     {         goto Error;     }     ret = avio_open2(&ofmt_ctx->pb, fileName, AVIO_FLAG_READ_WRITE, NULL, NULL);     if (ret < 0)     {         goto Error;     }     //InitEncoderCodec(640,480);     InitEncoderCodec(ic_ctx_v->width, ic_ctx_v->height);     //InitEncoderCodec(ic_ctx_v->width*1/2, ic_ctx_v->height*1/2);         av_dump_format(ofmt_ctx, 0, fileName, 1);     ret = avformat_write_header(ofmt_ctx, NULL);     if (ret < 0)     {         goto Error;     }     if (ret >= 0)         cout << "open output stream successfully" << endl;     return ret; Error:     if (ofmt_ctx)     {         avformat_close_input(&ofmt_ctx);     }     return ret; }   void CloseInput() {     if (ifmt_ctx)     {         avformat_close_input(&ifmt_ctx);     } }   void CloseOutput() {     if (ofmt_ctx)     {         avcodec_close(oc_ctx_v);         avformat_close_input(&ofmt_ctx);     } }   int InitFilter(AVCodecContext * codecContext) {     char args[512];     int ret = 0;       AVFilter *buffersrc = avfilter_get_by_name("buffer");     AVFilter *buffersink = avfilter_get_by_name("buffersink");     AVFilterInOut *outputs = avfilter_inout_alloc();     AVFilterInOut *inputs = avfilter_inout_alloc();     //string  filters_descr = "scale=640:480";     //string   filters_descr = "movie=my_logo.png[wm];[in][wm]overlay=5:5[out]";     //string   filters_descr = "drawtext=fontfile=arial.ttf:fontcolor=white:fontsize=36:text='Lei Xiaohua':x=20:y=20";     //string   filters_descr = "drawbox=x=100:y=100:w=100:h=100:color=pink@0.5";//画正方形     //string   filters_descr = "crop=1/2*in_w:1/2*in_h:0:0";          string   filters_descr =  "drawtext=fontfile=FreeSerif1.ttf:fontcolor=white:fontsize=36:text='Hello FFmpeg':x=18:y=200";       //const char *filter_descr = "lutyuv='u=128:v=128'";     //const char *filter_descr = "boxblur";     //const char *filter_descr = "hflip";     //const char *filter_descr = "hue='h=60:s=-3'";     //const char *filter_descr = "crop=2/3*in_w:2/3*in_h";     //const char *filter_descr = "drawbox=x=100:y=100:w=100:h=100:color=pink@0.5";     //const char *filter_descr = "drawtext=fontfile=arial.ttf:fontcolor=green:fontsize=30:text='Lei Xiaohua'";       enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };       filter_graph = avfilter_graph_alloc();     if (!outputs || !inputs || !filter_graph) {         ret = AVERROR(ENOMEM);         goto end;     }       /* buffer video source: the decoded frames from the decoder will be inserted here. */     sprintf_s(args, sizeof(args),         "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",         codecContext->width, codecContext->height, codecContext->pix_fmt,         codecContext->time_base.num, codecContext->time_base.den,         codecContext->sample_aspect_ratio.num, codecContext->sample_aspect_ratio.den);       ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",         args, NULL, filter_graph);     if (ret < 0) {         printf("Cannot create buffer source\n");         goto end;     }       /* buffer video sink: to terminate the filter chain. */     ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",         NULL, NULL, filter_graph);     if (ret < 0) {         printf("Cannot create buffer sink\n");         goto end;     }       ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts,         AV_PIX_FMT_YUV420P, AV_OPT_SEARCH_CHILDREN);     if (ret < 0) {         printf("Cannot set output pixel format\n");         goto end;     }       /* Endpoints for the filter graph. */     outputs->name = av_strdup("in");     outputs->filter_ctx = buffersrc_ctx;     outputs->pad_idx = 0;     outputs->next = NULL;       inputs->name = av_strdup("out");     inputs->filter_ctx = buffersink_ctx;     inputs->pad_idx = 0;     inputs->next = NULL;     if ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr.c_str(),         &inputs, &outputs, NULL)) < 0) {         printf("avfilter_graph_parse_ptr failed\n");         goto end;     }         if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) {         printf("avfilter_graph_config failed\n");         goto end;     }       return ret; end:     avfilter_inout_free(&inputs);     avfilter_inout_free(&outputs);     return ret; }         void addwatemake(char* y,int count,time_t *t,int bigwidth) {     struct tm *tm_now = localtime(t);     if (count % 25 == 0) {         (*t) +=1;     }     char tmp[64] = { 0 };     strftime(tmp, sizeof(tmp), "%Y-%m-%d %X", tm_now);     char* tmdate = (char*)malloc(patternLen);//2019-07-01 10:17:23     memset(tmdate, 0, patternLen);     memcpy(tmdate, tmp, patternLen - 1);     int size = num_width * num_height;     char *start = y + off_y * bigwidth + off_x;     for (int i = 0; i < patternLen; i++) {         int index = getIndex(*(tmdate + i));         char *num = mNumArrays + size * index;           for (int j = 0; j < num_height; j++) {             char *destIndex = start + i * num_width;               for (int k = 0; k < num_width; k++) {                 if (*(num + j * num_width + k) == 1) {                     *(destIndex + j * bigwidth + k) = 235;//水印文字颜色,235为白色,16为黑色                 }             }         }     }     free(tmdate);      }       int main(int argc, char* argv[]) {     int ret;     string fileInput = "love_360p.flv";     string fileOutput = "out.flv";     Init();         if (OpenInput((char *)fileInput.c_str()) < 0)     {         cout << "Open file Input failed!" << endl;           return 0;     }     if (OpenOutput((char *)fileOutput.c_str()) < 0)     {         cout << "Open file Output failed!" << endl;           return 0;     }     ret = InitFilter(ic_ctx_v);          AVFrame*  filterFrame = av_frame_alloc();     AVPacket* packet = (AVPacket*)av_malloc(sizeof(AVPacket));     av_init_packet(packet);     packet->data = NULL;     packet->size = 0;     int packetCount = 0;          initWatemake();     time_t t = time(0);     int count = 0;     char* testdata = (char*)malloc(640 * 360);     memset(testdata, 0, 640 * 360);     AVFrame* pSrcFrame2 = av_frame_alloc();     /*uint8_t *video_data_buffer = NULL;     video_data_buffer = new uint8_t[avpicture_get_size(ic_ctx_v->pix_fmt, ic_ctx_v->width, ic_ctx_v->height)];     avpicture_fill((AVPicture *)pSrcFrame2, video_data_buffer, ic_ctx_v->pix_fmt, ic_ctx_v->width, ic_ctx_v->height); */       while (1)     {         ret = av_read_frame(ifmt_ctx, packet);         if (ret < 0) {             break;         }         if (packet->stream_index != iv_index) {             continue;         }           int got_frame = 0;         AVFrame* pSrcFrame = av_frame_alloc();                  ret = avcodec_decode_video2(ic_ctx_v, pSrcFrame, &got_frame, packet);         if (ret < 0) {             printf("Error decoding video\n");             break;         }         if (got_frame) {             count++;                          memcpy(testdata, pSrcFrame->data[0], 640 * 360);               addwatemake(testdata, count, &t, ic_ctx_v->width);                          av_frame_ref(pSrcFrame2, pSrcFrame);             memcpy(pSrcFrame2->data[0], testdata, 640 * 360);                          pSrcFrame2->pts = av_frame_get_best_effort_timestamp(pSrcFrame);             /* push the decoded frame into the filtergraph */             if (av_buffersrc_add_frame_flags(buffersrc_ctx, pSrcFrame2, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {                 av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");                 break;             }               /* pull filtered frames from the filtergraph */             while (1) {                 ret = av_buffersink_get_frame(buffersink_ctx, filterFrame);                 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)                     break;                 if (ret < 0)                     goto end;                 AVPacket *opkt = (AVPacket *)av_malloc(sizeof(AVPacket));                 av_init_packet(opkt);                 opkt->data = NULL;                 opkt->size = 0;                 int got_output;                 filterFrame->pict_type = AV_PICTURE_TYPE_NONE;                   ret = avcodec_encode_video2(oc_ctx_v, opkt, filterFrame, &got_output);                 if (ret >= 0 && got_output)                 {                       packetCount += 40;                     opkt->pts = opkt->dts = packetCount;                     int ret = av_write_frame(ofmt_ctx, opkt);                 }                 av_free_packet(opkt);                 av_frame_unref(filterFrame);             }                      }                  av_frame_free(&pSrcFrame);                       }     free(testdata); end:     CloseInput();     CloseOutput();     cout << "end!" << endl;     return 0; }          

代码中640,360是我使用的测试视频的宽高,大家可以自己修改,我就懒得改了。

主要讲一个坑点,就是decode出来的frame不要修改它的data,自己去复制一个使用。这就是为什么程序中引入了pSrcFrame2,而不是直接用pSrcFrame。

代码自己琢磨吧,我就不吧啦吧啦了,不懂的留言

 

 

———————————————— 版权声明:本文为博主「bixinwei」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/bixinwei22/article/details/94454258

最新回复(0)