当前位置:编程学习 > JAVA >>

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帧   
80.uint8_t * rgb_buff = new uint8_t[nDataLen];
中的nDataLen是什么样的格式不是很明白。 --------------------编程问答--------------------
引用 5 楼 lvyunxing 的回复:
感谢你们的帮助,我是做Android 的,现在有个问题是我从SDCard中读取的图片或是Bitmap对象的图片数据怎样转成AVFrame->data[0]所需要的数据。这种转格式完全不会,网上这篇文章(http://blog.csdn.net/eightdegree/article/details/7425635)跟我想要的类似,但是有点看不明白,
//将rgb图像数据填充rgb帧   
80.uint8_t * rgb_buff = new uint8_t[nDataLen];
中的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();
avcodec_register_all();
两句话也加了,还是为空,但是codec = avcodec_find_decoder(CODEC_ID_H264);这个可以,不为空。求救 --------------------编程问答--------------------
引用 8 楼 lvyunxing 的回复:
你碰到过codec = avcodec_find_encoder(CODEC_ID_H264);其中codec总是空的,这个
avcodec_init();
avcodec_register_all();
两句话也加了,还是为空,但是codec = avcodec_find_decoder(CODEC_ID_H264);这个可以,不为空。求救



ffmpeg里默认没有h264编码,有h264解码,所以就是你的这个现象
编译ffmpeg时,把x264带进去,才会是你想要的结果 --------------------编程问答-------------------- 通过ffmpeg编码h264还是比较别扭的,就是即使有h264了,它也需要设置更多的参数,avcodec_open(或者avcodec_open2)才能成功,你可以先试试mpeg4的编码,后缀存成m4v,vlc播放器就可以直接播放

h264直接调用x264库编可能更方便一些,后缀h264时,vlc播放器可以播放 --------------------编程问答-------------------- 很感谢你细心的帮助,让我学到了很多
补充:Java ,  Java相关
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,