[原]从管道传送数据到ffmpeg进行视频编码

在windows编译ffmpeg,一般的方法是mingw+msys,编译出来的是windows的可执行文件ffmpeg.exe。

阅读 ffmpeg 源码的时候,发现 ffmpeg 支持 pipe,也就是说,传递给ffmpeg.exe进程的输入文件参数和输出文件参数不需要是硬盘文件路径,整个过程可以直接在内存完整。

测试方法:

1、用VC调用CreateNamedPipe创建一个命名管道,注意开辟的空间要至少能容纳1帧数据。

2、调用ConnectNamedPipe连接命名管道,这时程序会被挂起,直到有进程连接这个命名管道。

3、打开命令行,到ffmpeg目录,输入命令行:ffmpeg -f rawvideo -pix_fmt rgb24 -s 320x240 -i \\.\pipe\MyPipe -f avi -s 320x240 C:\out.avi

4、这时VC进程被唤醒,ffmpeg进程挂起等待图像数据写入。VC进程调用WriteFile写图像数据到命名管道。(注意写入的数据格式,必须跟命令行传入的参数一致)

5、当命名管道被写入数据时,ffmpeg自动唤醒进行编码,编码完一帧后继续挂起等待下一帧数据,如此重复。


转自http://hi.baidu.com/lzj85/blog/item/2d562f44ea3c9146500ffe50.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Qt使用FFmpeg进行视频编码的步骤如下: 1. 引入FFmpeg库:在Qt项目中引入FFmpeg库,可以通过在.pro文件中添加相应的库路径和链接库来实现。 2. 初始化FFmpeg:在使用FFmpeg之前,需要进行初始化。可以通过调用`av_register_all()`函数来完成初始化。 3. 创建AVFormatContext:AVFormatContext是FFmpeg中的一个重要结构体,用于存储音视频封装格式的相关信息。可以通过调用`avformat_alloc_output_context2()`函数来创建AVFormatContext对象。 4. 打开输出文件:使用`avio_open()`函数打开输出文件,并将文件指针赋值给AVFormatContext的pb字段。 5. 添加视频流:创建AVStream对象,并设置相关参数,如编码器、分辨率、帧率等。然后将AVStream对象添加到AVFormatContext中。 6. 打开视频编码器:使用`avcodec_find_encoder()`函数查找合适的视频编码器,并通过调用`avcodec_open2()`函数打开编码器。 7. 分配AVFrame:AVFrame用于存储视频帧的数据。可以通过调用`av_frame_alloc()`函数来分配AVFrame对象。 8. 编码视频帧:将始的RGB数据转换为YUV格式,并将YUV数据填充到AVFrame中。然后调用`avcodec_send_frame()`函数将AVFrame发送给编码器进行编码。 9. 获取编码后的数据:使用`avcodec_receive_packet()`函数从编码器中获取编码后的数据。 10. 写入文件:将编码后的数据写入输出文件中,可以通过调用`av_write_frame()`函数来实现。 11. 释放资源:在完成视频编码后,需要释放所有的资源,包括AVFormatContext、AVStream、AVCodecContext、AVFrame等对象。 以下是一个使用Qt和FFmpeg进行视频编码的示例代码: ```cpp #include <QCoreApplication> #include <QDebug> #include <QImage> #include <QFile> #include <QBuffer> extern "C" { #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h> } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 初始化FFmpeg av_register_all(); // 创建AVFormatContext AVFormatContext *formatContext = nullptr; avformat_alloc_output_context2(&formatContext, nullptr, nullptr, "output.mp4"); // 打开输出文件 QFile outputFile("output.mp4"); if (!outputFile.open(QIODevice::WriteOnly)) { qDebug() << "Failed to open output file"; return a.exec(); } AVIOContext *ioContext = nullptr; avio_open(&ioContext, outputFile.fileName().toUtf8().constData(), AVIO_FLAG_WRITE); formatContext->pb = ioContext; // 添加视频流 AVStream *videoStream = avformat_new_stream(formatContext, nullptr); if (!videoStream) { qDebug() << "Failed to create video stream"; return a.exec(); } // 设置视频流参数 AVCodecContext *codecContext = videoStream->codec; codecContext->codec_id = AV_CODEC_ID_H264; codecContext->codec_type = AVMEDIA_TYPE_VIDEO; codecContext->width = 640; codecContext->height = 480; codecContext->time_base = {1, 25}; codecContext->gop_size = 10; codecContext->pix_fmt = AV_PIX_FMT_YUV420P; // 打开视频编码器 AVCodec *codec = avcodec_find_encoder(codecContext->codec_id); if (!codec) { qDebug() << "Failed to find video encoder"; return a.exec(); } if (avcodec_open2(codecContext, codec, nullptr) < 0) { qDebug() << "Failed to open video encoder"; return a.exec(); } // 分配AVFrame AVFrame *frame = av_frame_alloc(); frame->format = codecContext->pix_fmt; frame->width = codecContext->width; frame->height = codecContext->height; av_frame_get_buffer(frame, 0); // 编码视频帧 AVPacket packet; av_init_packet(&packet); packet.data = nullptr; packet.size = 0; // 假设有一张RGB格式的图片 QImage image("input.png"); if (image.isNull()) { qDebug() << "Failed to load input image"; return a.exec(); } QImage yuvImage = image.convertToFormat(QImage::Format_YUV420P); // 将YUV数据填充到AVFrame中 for (int y = 0; y < codecContext->height; y++) { memcpy(frame->data[0] + y * frame->linesize[0], yuvImage.constBits() + y * yuvImage.bytesPerLine(), frame->linesize[0]); } for (int y = 0; y < codecContext->height / 2; y++) { memcpy(frame->data[1] + y * frame->linesize[1], yuvImage.constBits() + yuvImage.bytesPerLine() * codecContext->height + y * yuvImage.bytesPerLine() / 2, frame->linesize[1]); memcpy(frame->data[2] + y * frame->linesize[2], yuvImage.constBits() + yuvImage.bytesPerLine() * codecContext->height * 5 / 4 + y * yuvImage.bytesPerLine() / 2, frame->linesize[2]); } // 发送AVFrame给编码器进行编码 avcodec_send_frame(codecContext, frame); // 获取编码后的数据 while (avcodec_receive_packet(codecContext, &packet) == 0) { // 写入文件 av_write_frame(formatContext, &packet); av_packet_unref(&packet); } // 写入文件尾部 av_write_trailer(formatContext); // 释放资源 av_frame_free(&frame); avcodec_close(codecContext); avio_close(formatContext->pb); avformat_free_context(formatContext); qDebug() << "Video encoding finished"; return a.exec(); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值