FFmpeg 合成视频
谁知道FFmpeg怎么将本地图片合成视频吗?最近在做这个,我想要C代码,不要命令,网上都是命令的形式做的,求大神指导? --------------------编程问答-------------------- 要完成你说的功能,自己写代码调用ffmpeg库实现还是需要不少代码的。首先需要ffmpeg库,如果是win系统,我用minggw编译的(最好都是最新的版本,出现过最新的mingw编译不过0.8.15(我以前用这个版本,想出现编译一个发现编译不过)版本的ffmpeg),如果是linux编译更简单一些。然后需要调用avformat(及avcodec)的函数解码 图片,得到yuv的数据
然后需要调用avcodec或者x264的库生成视频流
最后用avformat打包成你想要的媒体格式
http://download.csdn.net/download/himulakensin/5224802里面有一些调用ffmpeg库的代码(ffmpeg 0.8版本的,ffmpeg后面版本更新的很快,但是只是多了一堆filter和扩展了一些格式的支持,以及有些函数名给换了,特别是读写文件的接口)
你可以可以参考ffmpeg自己提供的简单的例子文件(mingw make install后会放在/local/share下 --------------------编程问答-------------------- 恩恩,最近我在网上看了很多资料,基本调用,和步骤清楚了,现在又一个问题,怎么将获取的Bitmap货jpg图片转换成FFmpeg 的AVFrame数据,网上没有这方面的例子,有点崩溃了,都是从一个视频转换成一个新的视频。我现在是想读取SDCard中的图片,将这些图片编码成视频。不知道你做过这方面的没,有的话能否贴出来看看,小弟在此感激你啦! --------------------编程问答-------------------- http://download.csdn.net/download/himulakensin/5224802里相关ffmpeg的代码在afterglow里,正好里面没有没有出来图片的,后来我补了一个存图片的函数(jpg,png或者bmp等),但是没补读图片的。但大体上都差不多,都是照着format的例子写的,主要是要主要像jpg一般用颜色空间有些不一样(YUVJ422P?),里面类KsSwscale封装了一下,可以在各种颜色空间之间转换。一般视频编码需要I420的数据
这里贴出存图片的函数,仅供参考,good luck
int pifu::ks_output_image(const char * e_filename, ks_image_t *src, int bitrate)--------------------编程问答-------------------- 我总结的教程
{
char suffix[128];
ks_get_suffix(e_filename, suffix);
if (strcmp(suffix, ".jpg") != 0 &&
strcmp(suffix, ".jpeg") != 0 &&
strcmp(suffix, ".png") != 0 &&
strcmp(suffix, ".bmp") != 0 )
return -1;
ks_av_register_all();
AVFormatContext * oc = NULL;
/* allocate the output media context */
avformat_alloc_output_context2(&oc, NULL, NULL, e_filename);
if (!oc)
return -1;
if (strcmp(suffix, ".jpg") == 0 || strcmp(suffix, ".jpeg") == 0 ){
oc->oformat->video_codec = CODEC_ID_MJPEG;
}
else if (strcmp(suffix, ".png") == 0){
oc->oformat->video_codec = CODEC_ID_PNG;
}
else if (strcmp(suffix, ".bmp") == 0){
oc->oformat->video_codec = CODEC_ID_BMP;
}
else{
av_free(oc);
return -1;
}
AVCodecContext *c;
AVStream *st;
st = av_new_stream(oc, 0);
if (!st) {
av_free(oc);
return -1;
}
av_dump_format(oc, 0, e_filename, 1);
c = st->codec;
c->codec_id = oc->oformat->video_codec;
c->codec_type = AVMEDIA_TYPE_VIDEO;
/* put sample parameters */
if (bitrate == 0)
bitrate = src->i_width*src->i_height/5;
c->bit_rate = bitrate; // 无用??
/* resolution must be a multiple of two */
c->width = src->i_width;
c->height = src->i_height;
c->time_base.den = 25;
c->time_base.num = 1;
c->gop_size = 12; /* emit one intra frame every twelve frames at most */
if (c->codec_id == CODEC_ID_MJPEG)
c->pix_fmt = PIX_FMT_YUVJ422P;
else if (c->codec_id == CODEC_ID_PNG)
c->pix_fmt = PIX_FMT_RGB24;
else if (c->codec_id == CODEC_ID_BMP)
c->pix_fmt = PIX_FMT_BGR24;
// some formats want stream headers to be separate
if(oc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
AVCodec * codec = avcodec_find_encoder(c->codec_id);
if (!codec) {
av_free(oc);
return -1;
}
/* open the codec */
if (avcodec_open(c, codec) < 0) {
av_free(oc);
return -1;
}
//avcodec_encode_video
AVFrame * picture = ks_alloc_picture(c->pix_fmt, c->width, c->height);
if (!picture) {
avcodec_close(c);
av_free(oc);
return -1;
}
if (avio_open(&oc->pb, e_filename, AVIO_FLAG_WRITE) < 0) {
avcodec_close(c);
av_free(oc);
return -1;
}
av_write_header(oc);
int video_outbuf_size = c->width*c->height*3 + 1000000;
uint8_t *video_outbuf = (uint8_t *)av_malloc(video_outbuf_size);
int csp_type;
if (c->codec_id == CODEC_ID_MJPEG)
csp_type = PIFU_CSP_YUVJ422P;
else if (c->codec_id == CODEC_ID_PNG)
csp_type = PIFU_CSP_RGB;
else if (c->codec_id == CODEC_ID_BMP)
csp_type = PIFU_CSP_BGR;
pifu::ks_image_t pic(csp_type, c->width, c->height);
pifu::KsSwscale sws;
sws.scale(src, &pic);
if (csp_type == PIFU_CSP_YUVJ422P)
{
for (int i = 0; i < c->height; i++)
memcpy(picture->data[0] + i*picture->linesize[0], pic.plane[0] + i*pic.i_stride[0], c->width);
for (int i = 0; i < c->height; i++)
{
memcpy(picture->data[1] + i*picture->linesize[1], pic.plane[1] + i*pic.i_stride[1], c->width/2);
memcpy(picture->data[2] + i*picture->linesize[2], pic.plane[2] + i*pic.i_stride[2], c->width/2);
}
}
else
{
for (int i = 0; i < c->height; i++)
memcpy(picture->data[0] + i*picture->linesize[0], pic.plane[0] + i*pic.i_stride[0], c->width*3);
}
int out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
/* if zero size, it means the image was buffered */
if (out_size > 0) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.pts = 0;
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index= 0;
pkt.data= video_outbuf;
pkt.size= out_size;
av_interleaved_write_frame(oc, &pkt);
}
av_write_trailer(oc);
avcodec_close(c);
av_free(picture->data[0]);
av_free(picture);
//avformat_free_context(oc);
av_freep(&oc->streams[0]);
avio_close(oc->pb);
av_free(oc);
av_free(video_outbuf);
return 0;
}
[总结]FFMPEG视音频编解码零基础学习方法 --------------------编程问答-------------------- 感谢你们的帮助,我是做Android 的,现在有个问题是我从SDCard中读取的图片或是Bitmap对象的图片数据怎样转成AVFrame->data[0]所需要的数据。这种转格式完全不会,网上这篇文章(http://blog.csdn.net/eightdegree/article/details/7425635)跟我想要的类似,但是有点看不明白,
//将rgb图像数据填充rgb帧中的nDataLen是什么样的格式不是很明白。 --------------------编程问答--------------------
80.uint8_t * rgb_buff = new uint8_t[nDataLen];
AVFrame结构体前面几个数据比较常用
typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
uint8_t *data[AV_NUM_DATA_POINTERS];
int linesize[AV_NUM_DATA_POINTERS];
uint8_t **extended_data;
int width, height;
。。。。。
AVFrame表示视频时,你把data[0]指针理解为矩形的图片 大小linesize[0] x height,(linesize[0] >= width), 然后假设你有的数据是bmp的(如BGRA格式,一个像素点占4个字节),也是一个矩形width x height的数据,你用memcpy每行拷贝数据复制到data[0]就ok了(也就是是看的链接里 avpicture_fill 的功能)
可以看的data可能还有data[1] data[2] ...
我们常用编码视频的格式I420(YUV420)是三个plane的AVFrame,也就是要用到 data[0] data[1] data[2],分别表示Y、U、V三个分量。
RGB YUV这些基本概念还是需要很熟悉的知道的, 至少能先熟悉用ffmpeg里的swscale --------------------编程问答-------------------- 感谢你,这么细心给我解释。我QQ:1101150926,我们可以私下交流。 --------------------编程问答-------------------- 你碰到过codec = avcodec_find_encoder(CODEC_ID_H264);其中codec总是空的,这个
avcodec_init();两句话也加了,还是为空,但是codec = avcodec_find_decoder(CODEC_ID_H264);这个可以,不为空。求救 --------------------编程问答--------------------
avcodec_register_all();
ffmpeg里默认没有h264编码,有h264解码,所以就是你的这个现象
编译ffmpeg时,把x264带进去,才会是你想要的结果 --------------------编程问答-------------------- 通过ffmpeg编码h264还是比较别扭的,就是即使有h264了,它也需要设置更多的参数,avcodec_open(或者avcodec_open2)才能成功,你可以先试试mpeg4的编码,后缀存成m4v,vlc播放器就可以直接播放
h264直接调用x264库编可能更方便一些,后缀h264时,vlc播放器可以播放 --------------------编程问答-------------------- 很感谢你细心的帮助,让我学到了很多
补充:Java , Java相关