转: 最简单的基于FFmpeg的AVfilter例子(水印叠加)

该例子完成了一个水印叠加的功能。可以将一张透明背景的PNG图片作为水印叠加到一个视频文件上。

1. [代码][C/C++]代码


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

/**

 * 最简单的基于FFmpeg的AVFilter例子(叠加水印)

 * Simplest FFmpeg AVfilter Example (Watermark)

 *

 * 雷霄骅 Lei Xiaohua

 * [email protected]

 * 中国传媒大学/数字电视技术

 * Communication University of China / Digital TV Technology

 * http://blog.csdn.net/leixiaohua1020

 *

 * 本程序使用FFmpeg的AVfilter实现了视频的水印叠加功能。

 * 可以将一张PNG图片作为水印叠加到视频上。

 * 是最简单的FFmpeg的AVFilter方面的教程。

 * 适合FFmpeg的初学者。

 *

 * This software uses FFmpeg‘s AVFilter to add watermark in a video file.

 * It can add a PNG format picture as watermark to a video file.

 * It‘s the simplest example based on FFmpeg‘s AVFilter.

 * Suitable for beginner of FFmpeg

 *

 */

#include "stdafx.h"

#define ENABLE_SDL 1

#define ENABLE_YUVFILE 0

extern "C"

{

#include "libavcodec/avcodec.h"

#include "libavformat/avformat.h"

#include "libavfilter/avfiltergraph.h"

#include "libavfilter/avcodec.h"

#include "libavfilter/buffersink.h"

#include "libavfilter/buffersrc.h"

#include "libavutil/avutil.h"

#include "libswscale/swscale.h"

    //SDL

#include "sdl/SDL.h"

#include "sdl/SDL_thread.h"

};

const char *filter_descr = "movie=my_logo.png[wm];[in][wm]overlay=5:5[out]";

static AVFormatContext *pFormatCtx;

static AVCodecContext *pCodecCtx;

AVFilterContext *buffersink_ctx;

AVFilterContext *buffersrc_ctx;

AVFilterGraph *filter_graph;

static int video_stream_index = -1;

static int64_t last_pts = AV_NOPTS_VALUE;

static int open_input_file(const char *filename)

{

    int ret;

    AVCodec *dec;

    if ((ret = avformat_open_input(&pFormatCtx, filename, NULL, NULL)) < 0) {

        av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");

        return ret;

    }

    if ((ret = avformat_find_stream_info(pFormatCtx, NULL)) < 0) {

        av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");

        return ret;

    }

    /* select the video stream */

    ret = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);

    if (ret < 0) {

        av_log(NULL, AV_LOG_ERROR, "Cannot find a video stream in the input file\n");

        return ret;

    }

    video_stream_index = ret;

    pCodecCtx = pFormatCtx->streams[video_stream_index]->codec;

    /* init the video decoder */

    if ((ret = avcodec_open2(pCodecCtx, dec, NULL)) < 0) {

        av_log(NULL, AV_LOG_ERROR, "Cannot open video decoder\n");

        return ret;

    }

    return 0;

}

static int init_filters(const char *filters_descr)

{

    char args[512];

    int ret;

    AVFilter *buffersrc  = avfilter_get_by_name("buffer");

    AVFilter *buffersink = avfilter_get_by_name("ffbuffersink");

    AVFilterInOut *outputs = avfilter_inout_alloc();

    AVFilterInOut *inputs  = avfilter_inout_alloc();

    enum PixelFormat pix_fmts[] = { PIX_FMT_GRAY8, PIX_FMT_NONE };

    AVBufferSinkParams *buffersink_params;

    filter_graph = avfilter_graph_alloc();

    /* buffer video source: the decoded frames from the decoder will be inserted here. */

    _snprintf(args, sizeof(args),

            "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",

            pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,

            pCodecCtx->time_base.num, pCodecCtx->time_base.den,

            pCodecCtx->sample_aspect_ratio.num, pCodecCtx->sample_aspect_ratio.den);

    ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",

                                       args, NULL, filter_graph);

    if (ret < 0) {

        av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");

        return ret;

    }

    /* buffer video sink: to terminate the filter chain. */

    buffersink_params = av_buffersink_params_alloc();

    buffersink_params->pixel_fmts = pix_fmts;

    ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",

                                       NULL, buffersink_params, filter_graph);

    av_free(buffersink_params);

    if (ret < 0) {

        av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");

        return ret;

    }

    /* 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(filter_graph, filters_descr,

                                    &inputs, &outputs, NULL)) < 0)

        return ret;

    if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)

        return ret;

    return 0;

}

int _tmain(int argc, _TCHAR* argv[])

{

    int ret;

    AVPacket packet;

    AVFrame frame;

    int got_frame;

    if (argc != 2) {

        fprintf(stderr, "Usage: %s file\n", argv[0]);

        return -1;

    }

    avcodec_register_all();

    av_register_all();

    avfilter_register_all();

    if ((ret = open_input_file(argv[1])) < 0)

        goto end;

    if ((ret = init_filters(filter_descr)) < 0)

        goto end;

#if ENABLE_YUVFILE

    FILE *fp_yuv=fopen("test.yuv","wb+");

#endif

#if ENABLE_SDL

    SDL_Surface *screen;

    SDL_Overlay *bmp;

    SDL_Rect rect;

    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { 

        printf( "Could not initialize SDL - %s\n", SDL_GetError());

        return -1;

    }

    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);

    if(!screen) { 

        printf("SDL: could not set video mode - exiting\n"); 

        return -1;

    }

    bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,SDL_YV12_OVERLAY, screen);

#endif

    /* read all packets */

    while (1) {

        AVFilterBufferRef *picref;

        if ((ret = av_read_frame(pFormatCtx, &packet)) < 0)

            break;

        if (packet.stream_index == video_stream_index) {

            avcodec_get_frame_defaults(&frame);

            got_frame = 0;

            ret = avcodec_decode_video2(pCodecCtx, &frame, &got_frame, &packet);

            if (ret < 0) {

                av_log(NULL, AV_LOG_ERROR, "Error decoding video\n");

                break;

            }

            if (got_frame) {

                frame.pts = av_frame_get_best_effort_timestamp(&frame);

                

                /* push the decoded frame into the filtergraph */

                if (av_buffersrc_add_frame(buffersrc_ctx, &frame) < 0) {

                    av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");

                    break;

                }

                /* pull filtered pictures from the filtergraph */

                while (1) {

                    ret = av_buffersink_get_buffer_ref(buffersink_ctx, &picref, 0);

                    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)

                        break;

                    if (ret < 0)

                        goto end;

                    if (picref) {

#if ENABLE_YUVFILE

                        int y_size=picref->video->w*picref->video->h;

                        fwrite(picref->data[0],1,y_size,fp_yuv);

                        fwrite(picref->data[1],1,y_size/4,fp_yuv);

                        fwrite(picref->data[2],1,y_size/4,fp_yuv);

#endif

                        

#if ENABLE_SDL

                        SDL_LockYUVOverlay(bmp);

                        bmp->pixels[0]=picref->data[0];

                        bmp->pixels[2]=picref->data[1];

                        bmp->pixels[1]=picref->data[2];    

                        bmp->pitches[0]=picref->linesize[0];

                        bmp->pitches[2]=picref->linesize[1];  

                        bmp->pitches[1]=picref->linesize[2];

                        SDL_UnlockYUVOverlay(bmp);

                        rect.x = 0;   

                        rect.y = 0;   

                        rect.w = picref->video->w;   

                        rect.h = picref->video->h;   

                        SDL_DisplayYUVOverlay(bmp, &rect);

                        //Delay 40ms

                        SDL_Delay(40);

#endif

                        avfilter_unref_bufferp(&picref);

                    }

                }

            }

        }

        av_free_packet(&packet);

    }

#if ENABLE_YUVFILE

    fclose(fp_yuv);

#endif

end:

    avfilter_graph_free(&filter_graph);

    if (pCodecCtx)

        avcodec_close(pCodecCtx);

    avformat_close_input(&pFormatCtx);

    if (ret < 0 && ret != AVERROR_EOF) {

        char buf[1024];

        av_strerror(ret, buf, sizeof(buf));

        fprintf(stderr, "Error occurred: %s\n", buf);

        return -1;

    }

    return 0;

}

2. [图片] 20140509002339531.jpg

3. [图片] 20140509002355765.jpg

4. [图片] 20140608153919703.jpg

时间: 2024-11-08 22:00:55

转: 最简单的基于FFmpeg的AVfilter例子(水印叠加)的相关文章

最简单的基于FFmpeg的AVfilter例子(水印叠加)

FFMPEG中有一个类库:libavfilter.该类库提供了各种视音频过滤器.之前一直没有怎么使用过这个类库,最近看了一下它的使用说明,发现还是很强大的,有很多现成的filter供使用,完成视频的处理很方便.在此将它的一个例子基础上完成了一个水印叠加器,并且移植到了VC2010下,方便开发人员学习研究它的使用方法. 该例子完成了一个水印叠加的功能.可以将一张透明背景的PNG图片作为水印叠加到一个视频文件上. 下面直接贴上代码: /* * 最简单的基于FFmpeg的AVFilter例子(叠加水印

最简单的基于FFmpeg的AVfilter的例子-纯净版

===================================================== 最简单的基于FFmpeg的AVfilter例子系列文章: 最简单的基于FFmpeg的AVfilter例子(水印叠加) 最简单的基于FFmpeg的AVfilter的例子-纯净版 ===================================================== 有关FFmpeg的avfilter已经写过一个水印叠加的例子<最简单的基于FFmpeg的AVfilter例子

最简单的基于FFmpeg的AVfilter样例(水印叠加)

===================================================== 最简单的基于FFmpeg的AVfilter样例系列文章: 最简单的基于FFmpeg的AVfilter样例(水印叠加) 最简单的基于FFmpeg的AVfilter的样例-纯净版 ===================================================== FFMPEG中有一个类库:libavfilter.该类库提供了各种视音频过滤器. 之前一直没有怎么使用过这个

最简单的基于FFmpeg的AVDevice例子(读取摄像头)【转】

转自:http://blog.csdn.net/leixiaohua1020/article/details/39702113 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] libavdevice使用 注意事项 代码 结果 下载 =====================================================最简单的基于FFmpeg的AVDevice例子文章列表: 最简单的基于FFmpeg的AVDevice例子(读取摄像头) 最简单的基于FFm

最简单的基于FFmpeg的AVDevice例子(读取摄像头)

FFmpeg中有一个和多媒体设备交互的类库:Libavdevice.使用这个库可以读取电脑(或者其他设备上)的多媒体设备的数据,或者输出数据到指定的多媒体设备上.Libavdevice支持以下设备作为输入端: alsaavfoundationbktrdshowdv1394fbdevgdigrabiec61883jacklavfilibcdiolibdc1394openalosspulseqtkitsndiovideo4linux2, v4l2vfwcapx11grabdecklink Libav

最简单的基于FFmpeg的AVDevice例子(屏幕录制)

??FFmpeg中有一个和多媒体设备交互的类库:Libavdevice.使用这个库可以读取电脑的多媒体设备的数据,或者输出数据到指定的多媒体设备上. 计划写2个有关FFmpeg的libavdevice类库的例子.上篇文章记录了一个基于FFmpeg的Libavdevice类库读取摄像头数据的例子.本篇文章记录一个基于FFmpeg的Libavdevice类库录制屏幕的例子.本文程序录制当前桌面内容并且解码显示出来.有关解码显示方面的代码本文不再详述,可以参考文章:<100行代码实现最简单的基于FFM

最简单的基于FFmpeg的AVUtil例子 (AVLog, AVOption等)

本文的示例程序记录了FFmpeg的libavutil中几种工具函数的使用方法: AVLog:日志输出AVOption (AVClass):选项设置AVDictionary:键值对存储ParseUtil:字符串解析 几个libavutil的工具 AVLog AVLog是FFmpeg的日志输出工具.在FFmpeg中所有的日志输出不是通过printf()函数而是通过av_log()函数.av_log()会最终调用fprintf(stderr,-)函数将日志内容输出到命令行界面上.但是在一些非命令行程序

最简单的基于FFMPEG的转码程序 [转]

本文介绍一个简单的基于FFmpeg的转码器.它可以将一种视频格式(包括封转格式和编码格式)转换为另一种视频格式.转码器在视音频编解码处理的 程序中,属于一个比较复杂的东西.因为它结合了视频的解码和编码.一个视频播放器,一般只包含解码功能:一个视频编码工具,一般只包含编码功能:而一个视 频转码器,则需要先对视频进行解码,然后再对视频进行编码,因而相当于解码器和编码器的结合.下图例举了一个视频的转码流程.输入视频的封装格式是 FLV,视频编码标准是H.264,音频编码标准是AAC:输出视频的封装格式

最简单的基于FFmpeg的移动端例子:Android HelloWorld

从本文开始打算记录一系列FFmpeg在Android/IOS开发的示例程序.前面几篇文章记录FFmpeg安卓端开发的例子,后面几篇文章记录FFmpeg IOS端开发的例子.这些例子中FFmpeg相关的代码源自于<FFmpeg示例合集>中的程序.本文记录第一个程序:安卓平台下基于FFmpeg的HelloWorld程序. Android程序FFmpeg类库使用说明 Android应用程序使用FFmpeg类库的流程图如下所示. 上图中的流程可以分为"编译FFmpeg类库".&qu