【转】ffmpeg tutorial翻译——第一部分:制作屏幕录像

Qt写的Windows下屏幕录制程序源码 Qt + ffmpeg写的Windows屏幕录制程序(包含源程序和编译好的可执行程序) 程序使用方法: ScreenCapture w h w和h分别表示希望录制的帧宽度和高度 立即下载

 英文原文地址:http://www.dranger.com/ffmpeg/
转载翻译博客地址:http://blog.sina.com.cn/s/blog_46dc65a90100a91b.html

文中涉及的源码打包地址:http://www.dranger.com/ffmpeg/ffmpegsource.tar.gz

指导1:制作屏幕录像

源代码:tutorial01.c

概要

电影文件有很多基本的组成部分。首先,文件本身被称为容器Container ,容器的类型决定了信 息被存放在文件中的位置。AVI和Quicktime就是容器的例子。接着,你有一组流 ,例如,你经常有的是一个音频 流和一个视频流。(一个流只是一种想像出来的词语,用来表示一连串的通过时间来串连的数据元素)。在流中的数据元素被称为帧Frame 。 每个流是由不同的编码器来编码生成的。编解码器描述了实际的数据是如何被编码Coded和解码DECoded的,因此它的名字叫做CODEC。Divx和 MP3就是编解码器的例子。接着从流中被读出来的叫做包Packets。包是一段数据,它包含了一段可以被解码成方便我们最后在应用程序中操作的原始帧的 数据。根据我们的目的,每个包包含了完整的帧或者对于音频来说是许多格式的完整帧。

基本上来说,处理视频和音频流是很容易的:

10 从video.avi文件中打开视频流video_stream

20 从视频流中读取包到帧中

30 如果这个帧还不完整,跳到20

40 对这个帧进行一些操作

50 跳回到20

 

在这个程序中使用ffmpeg来处理多种媒体是相当容易的,虽然很多程序可能在对帧进行操作的时候非常的复杂。因此在这篇指导中,我们将打开一个文 件,读取里面的视频流,而且我们对帧的操作将是把这个帧写到一个PPM文件中。

打开文件

首先,来看一下我们如何打开一个文件。通过ffmpeg,你必需先初始化这个库。(注意在某些系统中必需 用<ffmpeg/avcodec.h>和<ffmpeg/avformat.h>来替换)

#include <avcodec.h>

#include <avformat.h>

...

int main(int argc, charg *argv[]) {

av_register_all();

这里注册了所有的文件格式和编解码器的库,所以它们将被自动的使用在被打开的合适格式的文件上。注意你只需要调用 av_register_all()一 次,因此我们在主函数main()中来调用它。如果你喜欢,也可以只注册特定的格式和编解码器,但是通常你没有必要这样做。

 

现在我们可以真正的打开文件:

AVFormatContext *pFormatCtx;

 

// Open video file

if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)

return -1; // Couldn't open file

我们通过第一个参数来获得文件名。这个函数读取文件的头部并且把信息保存到我们给的AVFormatContext结构体中。最后三个参数用来指定 特殊的文件格式,缓冲大小和格式参数,但如果把它们设置为空NULL或者0,libavformat将自动检测这些参数。

 

这个函数只是检测了文件的头部,所以接着我们需要检查在文件中的流的信息:

// Retrieve stream information

if(av_find_stream_info(pFormatCtx)<0)

return -1; // Couldn't find stream information

这个函数为pFormatCtx->streams填充上正确的信息。我们引进一个手工调试的函数来看一下里面有什么:

// Dump information about file onto standard error

dump_format(pFormatCtx, 0, argv[1], 0);

现在pFormatCtx->streams仅仅是一组大小为pFormatCtx->nb_streams的指针,所以让我们先跳过 它直到我们找到一个视频流。

int i;

AVCodecContext *pCodecCtx;

 

// Find the first video stream

videoStream=-1;

for(i=0; i<pFormatCtx->nb_streams; i++)

if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {

videoStream=i;

break;

}

if(videoStream==-1)

return -1; // Didn't find a video stream

 

// Get a pointer to the codec context for the video stream

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

流中关于编解码器的信息就是被我们叫做"codec context"(编解码器上下文)的东西。这里面包含了流中所使用的关于编解码器的所有信息,现在我们有了一个指向他的指针。但是我们必需要找到真正的 编解码器并且打开它:

AVCodec *pCodec;

 

// Find the decoder for the video stream

pCodec=avcodec_find_decoder(pCodecCtx->codec_id);

if(pCodec==NULL) {

fprintf(stderr, "Unsupported codec!/n");

return -1; // Codec not found

}

// Open codec

if(avcodec_open(pCodecCtx, pCodec)<0)

return -1; // Could not open codec

有些人可能会从旧的指导中记得有两个关于这些代码其它部分:添加CODEC_FLAG_TRUNCATED到 pCodecCtx->flags和添 加一个hack来粗糙的修正帧率。这两个修正已经不在存在于ffplay.c中。因此,我必需假设它们不再必要。我们移除了那些代码后还有一个需要指出的 不同点:pCodecCtx->time_base现在已经保存了帧率的信息。time_base是一个结构体,它里面有一个分子和分母 (AVRational)。我们使用分数的方式来表示帧率是因为很多编解码器使用非整数的帧率(例如NTSC使用29.97fps)。

 

保存数据

 

现在我们需要找到一个地方来保存帧:

AVFrame *pFrame;

 

// Allocate video frame

pFrame=avcodec_alloc_frame();

因为我们准备输出保存24位RGB色的PPM文件,我们必需把帧的格式从原来的转换为RGB。FFMPEG将为我们做这些转换。在大多数项目中(包 括我们的这个)我们都想把原始的帧转换成一个特定的格式。让我们先为转换来申请一帧的内存。

// Allocate an AVFrame structure

pFrameRGB=avcodec_alloc_frame();

if(pFrameRGB==NULL)

return -1;

即使我们申请了一帧的内存,当转换的时候,我们仍然需要一个地方来放置原始的数据。我们使用avpicture_get_size来获得我们需要的 大小,然后手工申请内存空间:

uint8_t *buffer;

int numBytes;

// Determine required buffer size and allocate buffer

numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,

pCodecCtx->height);

buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

av_malloc是ffmpeg的malloc,用来实现一个简单的malloc的包装,这样来保证内存地址是对齐的(4字节对齐或者2字节对 齐)。它并不能保护你不被内存泄漏,重复释放或者其它malloc的问题所困扰。

现在我们使用avpicture_fill来把帧和我们新申请的内存来结合。关于AVPicture的结成:AVPicture结构体是 AVFrame结构体的子集――AVFrame结构体的开始部分与AVPicture结构体是一样的。

// Assign appropriate parts of buffer to image planes in pFrameRGB

// Note that pFrameRGB is an AVFrame, but AVFrame is a superset

// of AVPicture

avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,

pCodecCtx->width, pCodecCtx->height);

最后,我们已经准备好来从流中读取数据了。

 

读取数据

 

我们将要做的是通过读取包来读取整个视频流,然后把它解码成帧,最好后转换格式并且保存。

int frameFinished;

AVPacket packet;

 

i=0;

while(av_read_frame(pFormatCtx, &packet)>=0) {

// Is this a packet from the video stream?

if(packet.stream_index==videoStream) {

// Decode video frame

avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,

packet.data, packet.size);

 

// Did we get a video frame?

if(frameFinished) {

// Convert the image from its native format to RGB

img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24,

(AVPicture*)pFrame, pCodecCtx->pix_fmt,

pCodecCtx->width, pCodecCtx->height);

 

// Save the frame to disk

if(++i<=5)

SaveFrame(pFrameRGB, pCodecCtx->width,

pCodecCtx->height, i);

}

}

 

// Free the packet that was allocated by av_read_frame

av_free_packet(&packet);

}

这个循环过程是比较简单的:av_read_frame()读取一个包并且把它保存到AVPacket结构体中。注意我们仅仅申请了一个包的结构体 ――ffmpeg为我们申请了内部的数据的内存并通过packet.data指针来指向它。这些数据可以在后面通过av_free_packet()来释 放。函数avcodec_decode_video()把包转换为帧。然而当解码一个包的时候,我们可能没有得到我们需要的关于帧的信息。因此,当我们得 到下一帧的时候,avcodec_decode_video()为我们设置了帧结束标志frameFinished。最后,我们使用 img_convert()函数来把帧从原始格式(pCodecCtx->pix_fmt)转换成为RGB格式。要记住,你可以把一个 AVFrame结构体的指针转换为AVPicture结构体的指针。最后,我们把帧和高度宽度信息传递给我们的SaveFrame函数。

关于包Packets的注释

从技术上讲一个包可以包含部分或者其它的数据,但是ffmpeg的解释器保证了我们得到的包Packets包含的要么是完 整的要么是多种完整的帧。

现在我们需要做的是让SaveFrame函数能把RGB信息定稿到一个PPM格式的文件中。我们将生成一个简单的PPM格式文件,请相信,它是可以 工作的。

void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {

FILE *pFile;

char szFilename[32];

int y;

 

// Open file

sprintf(szFilename, "frame%d.ppm", iFrame);

pFile=fopen(szFilename, "wb");

if(pFile==NULL)

return;

 

// Write header

fprintf(pFile, "P6/n%d %d/n255/n", width, height);

 

// Write pixel data

for(y=0; y<height; y++)

fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);

 

// Close file

fclose(pFile);

}

我们做了一些标准的文件打开动作,然后写入RGB数据。我们一次向文件写入一行数据。PPM格式文件的是一种包含一长串的RGB数据的文件。如果你 了解 HTML色彩表示的方式,那么它就类似于把每个像素的颜色头对头的展开,就像#ff0000#ff0000....就表示了了个红色的屏幕。(它被保存成 二进制方式并且没有分隔符,但是你自己是知道如何分隔的)。文件的头部表示了图像的宽度和高度以及最大的RGB值的大小。

现在,回顾我们的main()函数。一旦我们开始读取完视频流,我们必需清理一切:

// Free the RGB image

av_free(buffer);

av_free(pFrameRGB);

 

// Free the YUV frame

av_free(pFrame);

 

// Close the codec

avcodec_close(pCodecCtx);

 

// Close the video file

av_close_input_file(pFormatCtx);

 

return 0;

你会注意到我们使用av_free来释放我们使用avcode_alloc_fram和av_malloc来分配的内存。

上面的就是代码!下面,我们将使用Linux或者其它类似的平台,你将运行:

gcc -o tutorial01 tutorial01.c -lavutil -lavformat -lavcodec -lz -lavutil -lm

如果你使用的是老版本的ffmpeg,你可以去掉-lavutil参数:

gcc -o tutorial01 tutorial01.c -lavutil -lavformat -lavcodec -lz -lm

大多数的图像处理函数可以打开PPM文件。可以使用一些电影文件来进行测试。

FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK 本课程讲解的是基于流行的直播技术 FFMpeg3.3音视频处理框架,和应用广的c++跨平台的QT5库(主要用作界面)。开发的一个完整的屏幕录像机项目,包含桌面录制(基于 QT(跨平台),directx(高效)),话筒录制,音视频h264编码,MP4封装。QT圆角边框界面。开发工具基于vs2015,但同样适用于vs更高版本。 立即下载

相关推荐

视频处理 ffmepg+qt

ffmepg用来对视频进行编码 ,比如可以将视频编码成MP4格式,但是media信息会放在后面,可以使用qt将media信息放在开头可以实现边下载边播放

基于qt和ffmpeg视频播放器开发实战

ffmpeg是世界上应用广的开源视频处理框架,在各个平台(windows,linux,嵌入式、Android、IOS)被广泛应用,可以说是做视频相关项目技能qt是目前跨平台项目界面开发的第一选择,本课程基于这两种框架在加上VC++,给大家讲解延时如何开发出一个视频播放器,各个模块如何结合,如何考虑性能问题,如何设计封装类,如何处理各种异常情况。

在ros里给机械臂加上夹爪和底盘后,控制真实机械臂

使用ur3_bringup 可以连接真实机械臂 使用官方的ur3_moveit_planning_execution.launch 可以对机械臂 moveit规划。 但是只有机械臂,没有夹爪。 官方如图: 我把原来的ur3_moveit_config 复制出来,修改 然后把ur3.xacro 等模型文件复制出来修改,修改完之后,有了夹爪,有了底盘。 规划组什么的使用moveit setup assistant 配置过了。 在rviz中可以笛卡尔空间规划了。 ...

超级菜 2715

ffmpeg tutorial

第一部分:制作屏幕录像

xutom2006的专栏 1190

无源低通滤波器

无源RC滤波器“滤除”不需要的信号,因为它们分离并允许仅通过其频率的正弦输入信号,最简单的是无源低通滤波器网络。在低频应用(高达100kHz)中,无源滤波器通常使用简单的RC(电阻-电容)网络构建,而高频滤波器(高于100kHz)通常由RLC(电阻-电感-电容)元件制成。无源滤波器由电阻器、电容器和电感器等无源元件组成,没有放大元件(晶体管、运算放大器等),因此没有信号增益,因此它们的输出电平始终小于输入。滤波器是根据它们允许通过它们的信号的频率范围来命名的,同时阻挡或“衰减”其余部分。

weixin_44448586的博客 1万+

汇川伺服驱动器参数优化实战指南

本文详细介绍了汇川伺服驱动器参数优化的实战技巧,涵盖控制模式选择、电子齿轮比调整、刚性匹配与振动抑制等关键内容。通过实际案例和实用技巧,帮助工程师快速掌握伺服驱动器参数调校方法,提升设备运行精度和稳定性。特别针对高精度定位和高速响应场景提供了专业指导。

weixin_29070721的博客 731

ffmpeg tutorials(dranger) 翻译

ffmpeg文档 指导1:制作屏幕录像 源代码:tutorial01.c   概要   电影文件有很多基本的组成部分。首先,文件本身被称为容器Container,容器的类型决定了信息被存放在文件中的位置。AVI和Quicktime就是容器的例子。接着,你有一组流,例如,你经常有的是一个音频流和一个视频流。(一个流只是一种想像出来的词语,用来表示一

浠er 的优快云 2488

学习笔记( 11 ) - 解决:finalshell连接虚拟机(ubuntu)超时,主机ping不通虚拟机,主机没有VMnet8网卡, Connection refused: connect

解决:finalshell连接虚拟机(ubuntu)超时,主机ping不通虚拟机,主机没有VMnet8网卡, Connection refused: connect

烟溪彭于晏的博客 2万+

如何基于FFMPEG和SDL写一个少于1000行代码的视频播放器

原文地址:http://www.dranger.com/ffmpeg/   FFMPEG是一个很好的库,可以用来创建视频应用或者生成特定的工具。FFMPEG几乎为你把所有的繁重工作都做了,比如解码、编码、复用和解复用。这使得多媒体应用程序变得容易编写。它是一个简单的,用C编写的,快速的并且能够解码几乎所有你能用到的格式,当然也包括编码多种格式。 唯一的问题是它的文档基本上是没有的

jia_zhengshen的专栏 2015

Virtualbox “Kernel driver not installed (rc=-1908)”问题全面解析与修复指南

本文全面解析了Virtualbox出现'Kernel driver not installed (rc=-1908)'错误的原因及修复方法。详细介绍了如何通过重新安装virtualbox-dkms、处理Secure Boot特殊情况等步骤解决该问题,并提供了预防措施与最佳实践,帮助用户避免类似错误再次发生。

weixin_30352645的博客 528

Win10 + Linux 双系统删除(Linux)

删除Linux所使用的磁盘分区 进入此电脑->计算机->管理->磁盘管理

weixin_52247624的博客 943

FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-夏曹俊-专题视频课程...

本课程讲解的是基于流行的直播技术 FFMpeg3.3音视频处理框架,和应用广的c++跨平台的QT5库(主要用作界面)。开发的一个完整的屏幕录像机项目,包含桌面录制(基于 QT(跨平台),directx(高效)),话筒录制,音视频h264编码,MP4封装。QT圆角边框界面。 开发工具基于vs2015,但同样适用于vs更高版本。...

老夏课堂-夏曹俊的技术专栏 1129

基于V7-690T FPGA纯逻辑实现NVMe SSD盘的读写(不使用软核)

a.NVMe的Admin CQ与Admin SQ命令放在Host内存中;因此SQ的64B要用FPGA的DDR或开一个bram空间存放,同理NVME写到HOST的CQ命令也需要存放在FPGA的DDR或一个bram空间,host收到NVME传来的MSI/MSI-X中断后,去CQ存放空间取CQ指令;b. 发送identify命令后,需要发送tial doorbell通知NVME;(发送CNS01h获取4096字节的固件信息等;发送CNS02h获取1024字节的namaspace list)

宝沐熙的博客 832

学习笔记(01):FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-音视频编码类封装介绍和使用ffmpeg工具抽取rgb和pcm...

本课程讲解的是基于流行的直播技术 FFMpeg3.3音视频处理框架,和应用广的c++跨平台的QT5库(主要用作界面)。开发的一个完整的屏幕录像机项目,包含桌面录制(基于 QT(跨平台),directx(高效)),话筒录制,音视频h264编码,MP4封装。QT圆角边框界面。 开发工具基于vs2015,但同样适用于vs更高版本。...

H0ly_shiT的博客 570

【WorkBuddy从入门到精通实战教程】使用手册 第 1 章 初识 WorkBuddy

腾讯推出全场景AI办公助手WorkBuddy,突破传统聊天机器人局限,实现从需求理解到结果交付的全流程自动化。该工具通过自然语言交互,可自主规划执行复杂任务,包括文件处理、数据分析、PPT制作等,支持多模型切换和技能扩展。内置权限管控机制确保本地文件操作安全,显著降低人工切换工具的成本,提升职场效率。

企鹅码农的专属播客,分享10多年的实战案例和经验解读,包含YOLO、RT-DETR、AI等各个工作领域。 1249

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

FFmpeg音视频核心技术精讲与实战

一、日志:     &lt;libavutil/log.h&gt;头文件     av_set_log_level();  AV_LOG_DEBUG/AV_LOG_INFO/AV_LOG_WARNING/AV_LOG_ERROR     av_log(); 二、文件删除和重命名:     avpriv_io_delete();     avpriv_io_move(); 三、操作目录     av...

daitu3201的博客 3298

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

直播技术(从服务端到客户端)二

播放(播放方式研究) 在上一篇文章中,我们叙述了直播技术的环境配置(包括服务端nginx,nginx-rtmp-module, ffmpeg, Android编译,ios编译)。从本文开始,我们将叙述播放相关的东西,播放是直播技术中关键的一步,它包括很多技术如:解码,缩放,时间基线选择,缓存队列,画面渲染,声音播放等等。我将分为三个部分为大家讲述整个播放流程; Android

郭风朴(guofengpu)的Android影音专栏 1174

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

数据结构实战完全手册-夏曹俊-专题视频课程

数据结构是程序设计的必修知识,它是程序设计的基本功,并且在企业面试、日常工作、研究生入学考试中都占有重要的地位。不同于其他课程,本课程从单链表出发,手把手的全代码实现了栈与队列,树、图(包括数组和链表的两种形式),并对这些经典结构的应用也做了代码级的实现,覆盖了经典数据结构的全部内容...

老夏课堂-夏曹俊的技术专栏 1752
上一篇: Symbian 命令行编译、打包
下一篇: 【转】ffmpeg tutorial 2:输出到屏幕
code09
博客等级 码龄18年 31粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值