本人在ffmpeg movie滤镜添加图片水印博客中用命令行以及代码的方式,利用movie滤镜将jpg图片叠加到视频上。
其实,我们也可以将jpg直接转成yuv420,然后叠加到视频上,此时就不需要movie滤镜。
首先,将jpg转换成yuv420,可以用ffmpeg命令行,命令行如下:
ffmpeg -i flower.jpg -s 480x320 -pix_fmt yuv420p flower.yuv
这里定义了规格,480x320,其实原来的flower.jpg的规格是499x333,我为了linesize的对齐方便,将规格改成了480x320,图片如下所示:

合成效果如下:

main函数如下:
int main()
{
CDrawMyMovie cVideoDrawMovie;
const char *pFileA = "E:\\learn\\ffmpeg\\FfmpegFilterTest\\x64\\Release\\in-computer.mp4";
const char *pFileOut = "E:\\learn\\ffmpeg\\FfmpegFilterTest\\x64\\Release\\in-computer_drawmymovie.mp4";
std::string strMovieFile = "E:\\learn\\ffmpeg\\convert\\flower.yuv";
//std::string strMovieFile = "flower.jpg";
cVideoDrawMovie.StartDrawMyMovie(pFileA, pFileOut, 100, 300, strMovieFile, 480, 320);
cVideoDrawMovie.WaitFinish();
return 0;
}
这里面,100,300代表叠加的位置坐标。
y,u,v分量的读取很简单,因为它们在文件是依次存储的,读取方式如下所示:
int CDrawMyMovie::ReadMovieFile(const char *pFileMovie, int iWidth, int iHeight)
{
m_iMovieWidth = iWidth;
m_iMovieHeight = iHeight;
int ret = -1;
do
{
FILE *fp = fopen(pFileMovie, "rb");
if (NULL == fp)
{
break;
}
m_pMovieY = new uint8_t[iWidth * iHeight];
m_pMovieU = new uint8_t[iWidth * iHeight / 4];
m_pMovieV = new uint8_t[iWidth * iHeight / 4];
int iread = fread(m_pMovieY, 1, iWidth * iHeight, fp);
iread = fread(m_pMovieU, 1, iWidth * iHeight / 4, fp);
iread = fread(m_pMovieV, 1, iWidth * iHeight / 4, fp);
ret = 0;
} while (0);
return ret;
}
下面我们可以根据宽,高,yuv分量值构建水印图片的AVFrame
int iYuv420MovieFrameSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_iMovieWidth, m_iMovieHeight, 1);
AVFrame *pFrameVideoMovie = av_frame_alloc();
uint8_t *videoMovie_buffer_yuv420 = (uint8_t *)av_malloc(iYuv420MovieFrameSize);
av_image_fill_arrays(pFrameVideoMovie->data, pFrameVideoMovie->linesize, videoMovie_buffer_yuv420, AV_PIX_FMT_YUV420P, m_iMovieWidth, m_iMovieHeight, 1);
pFrameVideoMovie->width = m_iMovieWidth;
pFrameVideoMovie->height = m_iMovieHeight;
pFrameVideoMovie->format = AV_PIX_FMT_YUV420P;
memcpy(pFrameVideoMovie->data[0], m_pMovieY, m_iMovieWidth * m_iMovieHeight);
memcpy(pFrameVideoMovie->data[1], m_pMovieU, m_iMovieWidth * m_iMovieHeight / 4);
memcpy(pFrameVideoMovie->data[2], m_pMovieV, m_iMovieWidth * m_iMovieHeight / 4);
然后根据下面的代码进行两张图片的叠加
ret = av_buffersrc_add_frame(m_pFilterCtxSrcVideoA, pFrameVideoA);
if (ret < 0)
{
break;
}
ret = av_buffersrc_add_frame(m_pFilterCtxSrcVideoMovie, pFrameVideoMovie);
if (ret < 0)
{
break;
}
ret = av_buffersink_get_frame(m_pFilterCtxSink, pFrame_out);
if (ret < 0)
{
//printf("Mixer: failed to call av_buffersink_get_frame_flags\n");
break;
}
代码结构如下:

其中FfmpegMyMovieTest.cpp的内容如下:
#include <iostream>
#include "DrawMyMovie.h"
#include <vector>
#ifdef __cplusplus
extern "C"
{
#endif
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avdevice.lib")
#pragma comment(lib, "avfilter.lib")
#pragma comment(lib, "postproc.lib")
#pragma comment(lib, "swresample.lib")
#pragma comment(lib, "swscale.lib")
#ifdef __cplusplus
};
#endif
std::string Unicode_to_Utf8(const std::string & str)
{
int nwLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
wchar_t * pwBuf = new wchar_t[nwLen + 1];//一定要加1,不然会出现尾巴
ZeroMemory(pwBuf, nwLen * 2 + 2);
::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen);
int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
char * pBuf = new char[nLen + 1];
ZeroMemory(pBuf, nLen + 1);
::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
std::string retStr(pBuf);
delete[]pwBuf;
delete[]pBuf;
pwBuf = NULL;
pBuf = NULL;
return retStr;
}
int main()
{
CDrawMyMovie cVideoDrawMovie;
const char *pFileA = "E:\\learn\\ffmpeg\\FfmpegFilterTest\\x64\\Release\\in-computer.mp4";
const char *pFileOut = "E:\\learn\\ffmpeg\\FfmpegFilterTest\\x64\\Release\\in-computer_drawmymovie.mp4";
std::string strMovieFile = "E:\\learn\\ffmpeg\\convert\\flower.yuv";
//std::string strMovieFile = "flower.jpg";
cVideoDrawMovie.StartDrawMyMovie(pFileA

该博客介绍了如何利用ffmpeg命令行将jpg图片转换为yuv420格式,并在C++代码中实现将转换后的yuv图片叠加到视频上,省去了movie滤镜的使用。作者详细展示了从图片转换到视频处理的步骤,包括读取yuv文件、构建AVFrame、进行图片叠加等操作。
最低0.47元/天 解锁文章
722

被折叠的 条评论
为什么被折叠?



