显示标签为“ffmpeg”的博文。显示所有博文
显示标签为“ffmpeg”的博文。显示所有博文

2010年4月18日星期日

FFmpeg和SDL的API

使用FFmpeg的API和SDL的API进行视频的解码和显示,似乎还是有点技术含量的东西,我最近收到一些email询问视频的解码和显示的实现,今天hanyionet就献上博文一篇简单地说明一下如何使用这些API,其实使用这些API其实一点都不难,不要被复杂描述吓到。我们所要做就是先要了解视频的解码和显示到底是怎样的一个过程,然后了解各个API的作用。


进行解码和视频的现实一般来说就是这样的步骤:
初始化-->解码-->图像缩放-->视频显示
以下是一个简单的过程流程图,在每一个步骤中给出一些比较重要的API。

Process flow of video decode module new

可以看出,不同的步骤的实现,就是找到并使用相对应的API。
图中的API的具体说明,今天一同给出。

FFmpeg API

描述

av_register_all()

Initializes libavformat and registers all the muxers, demuxers and protocols.

avcodec_find_decoder(…)

Finds a decoder with a matching codec ID.

avcodec_alloc_context()

Allocates an AVCodecContext and sets its fields to default values.

avcodec_alloc_frame()

Allocates an AVFrame and sets its fields to default values.

sws_getContext(…)

Returns an SwsContext to be used in sws_scale().

sws_scale(…)

Scales the data in source according to our settings in our SwsContext c. srcStride and dstStride are the source and destination linesize.

avcodec_decode_video(…)

Decodes a video frame from buffer into picture.

 

SDL API

描述

SDL_SetVideoMode()

Set up a video mode with the specified width, height, and bits-per-pixel.

SDL_CreateYUVOverlay()

It is used to create a YUV overlay of the specified width, height and format for the provided display.

SDL_BlitSurface()

This performs a fast blit from the source surface to the destination surface.

SDL_FreeSurface()

Frees (deletes) a SDL surface.

SDL_UpdateRect()

Makes sure the given area is updated on the given screen.

SDL_Flip()

It is used to swap screen buffers. On hardware that supports double-buffering, this function sets up a flip and returns.

SDL_FreeYUVOverlay()

Free a YUV video overlay.

其实要理解FFmpeg的API还有一个非常重要的地方就是理解,各种数据结构的具体内容,譬如AVFrame和AVCodecContext,个人认为这两个结构是比较重要的。
了解的这些API的使用方法后,现在应该做的就是找一个例子例如ffplay.c或者http://dranger.com/ffmpeg/里的例程,体会一下,最后使用这些API搭建出属于自己的视频播放程序。

Enjoy!

2009年10月3日星期六

在MinGW中安装并使用GCC4.4.0

一直懒得升级MinGW的GCC,因为嫌麻烦,这真是一个很不好的习惯,其实我们应该要常常提醒自己是否“是否在使用最好最新的工具?”,一直到前几天在我的一个小程序使用FFmpeg的avcodec_encode_video()函数发生崩溃(Crash)后才决定升级GCC。avcodec_encode_video()函数发生崩溃是因为堆栈定向问题(stack alignment issue),有兴趣的可以看这个网页里的讨论:
http://ffmpeg.arrozcru.org/forum/viewtopic.php?f=1&t=549如果使用gcc >= 4.2版本就可以解决问题。

MinGW在2009年6月份已经释出了GCC 4.4.0请到以下的站点:http://sourceforge.net/projects/mingw/files/下载如下的文件(假设你只是要使用gcc,c++编译器,如果要使用java,objc,请下载其他相关的文档)
gcc-ada-4.4.0-mingw32-dll
gcc-core-4.4.0-mingw32-bin
gcc-core-4.4.0-mingw32-dll
gcc-c++-4.4.0-mingw32-bin
gcc-c++-4.4.0-mingw32-dll
gmp-4.2.4-mingw32-dll
mpfr-2.4.1-mingw32-dll
下完后,请直接解压到MinGW的目录中去,例如C:\MinGW里。

然后重新安装msys,很简单以前的文章就提过了,不要忘了下载coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2并且解压到msys的目录中去,因为在默认状态下msys并没有完全安装coreutils的所有组件。为什么要安装完整的coreutils组件呢,这是因为有些make文件里的指令需要coreutils的一些组件才能正确识别。coreutils的最新版可以http://ftp.gnu.org/pub/gnu/coreutils/里找到。

现在有了MinGW5.16+GCC4.4.0+msys,我对我常用的几个库进行了重新编译(理论上不需要对所有所使用的库重新编译,因为高版本的GCC应该向下兼容低版本的GCC所编译的库):

Qt4.5.1已经用了挺长的一段时间,9月30日我下载了了Qt4.5.2然后编译了它,没想到10月1日Qt释出了4.5.3。哈,不想再编译一遍了,因为即使使用配置了Core i7的机器,编译Qt也需要很长的时间。编译的方法如下:先将C:\MinGW\bin和C:\Qt\4.5.2\bin加入环境变量的path里。然后进入Qt by Nokia v4.5.2 --> Qt 4.5.2 Command Prompt并输入configure(当然了,可以进行configure调整,具体请输入configure --help看说明),最后输入mingw32-make,就开始编译了。

LIVE555也于28-Sep-2009已经释出了新版本,可到以下站点下载。http://live555.com/liveMedia/public/然后重新编译,很简单,解压下载完的原文档,然后通过msys进入它的目录,先输入./genMakefiles mingw然后输入make,就搞定了。如果遇到问题可能要对config.mingw进行一些微调,例如将第三行C_COMPILER =           $(CC)的改成C_COMPILER =           $ gcc

对FFmpeg编译可以按照以前介绍过的方法,但是编译好我的项目并正确连接编译好的ffmpeg动态库后,运行我的程序会出现这样的错误:"The application failed to initialize properly - 0xc0000005" 很无奈,我的解决方法比较愚蠢,重新编译FFmpeg生成静态链接库(.a),然后在项目设定中使用静态链接库代替动态库(.dll),结果程序可以正常运行,只是我的主程序增肥了不少,这是暂时的解决方法。

还编译了一些库,使用gcc4.4.0编译和使用几乎没有问题,这里就不多谈了。在网上找了一下我使用过的一些库,很多开源库都陆续释出新的版本,我使用的版本真的很旧了,使用开源库要常常注意它们的更新,还是那句话要常常“提醒自己是否在使用的最新最好的库”,很多库的新版本已经解决了一些我以前遇到的问题,我下载了一些库的二进制版(bin),然后可以直接使用它里面的dll就可以了,连编译都不用了。

2009年9月17日星期四

ffmpeg的使用,及发送媒体流的一些简单介绍

在以前的文章谈过对ffmpeg的编译。这里谈谈ffmpeg的最简单的使用。

ffmpeg使用语法:

ffmpeg [[options][`-i' input_file]]... {[options] output_file}...

最简单的使用:ffmpeg –i test_mp4.mp4 test_mpg.mpg (将输入的mp4容器格式的文件转换成mpg格式文件)

我在做一些机器人控制实验时常常会得到很多的jpg格式的文件,将这些文件改成连续的名称,例如test_jpg00001, test_jpg00002等等,然后可以通过ffmpeg生成一个视频文件,这会很方便演示,例如:
  ffmpeg -r 15 -b 1800 -i test_jpg00%03d.jpg test_mp4.mp4 (这里,-r 代表fps 设置帧频;–b 代表bitrate 设置比特率; test_jpg00%03d.jpg中%03d代表最后三位数字)

做实验时,直接通过摄像头可以得到raw picture(也就是YUV或RGB文件),这时也可以通过ffmpeg将它们转换成mpg或任意容器格式。例如:ffmpeg -s 320*240 -i test_yuv.yuv test_mpg.mpg (这里请注意在写入输入文件之前,必须给ffmpeg传入帧大小,也就是通过 –s 来设置帧大小)。当然了,你也可以将例如mpg格式的文件转换成YUV文件,即,ffmpeg -i test_mpg.mpg test_yuv.yuv。
 

除了转换格式ffmpeg还可以做更多的事,例如发送媒体流,通过rtp协议,可以输入以下的命令:

ffmpeg -fflags +genpts -re -i test.mpg -vcodec copy -an -f rtp rtp://127.0.0.1:10000 -vn -acodec copy -f rtp rtp://127.0.0.1:20000 -newaudio

其中,-re 代表本地帧频读数据;-an 代表不使能音频纪录;127.0.0.1也就是本地回环地址,我们常常使用它来测试本机的网络配置,通过PING127.0.0.1来检测本机的网卡和IP协议;当然我们还可以使用它来代替SERVER的IP地址,这样程序就可以在同一台机器上运行,所有的SERVER的资源就可以装在本机,我们程序就可以运行。

使用ffmpeg发送了媒体流后,我们可以在写字板里写一个SDP文件(附注:文件的后缀也是.sdp),例如:

v=0
  o=- 0 0 IN IPV4 127.0.0.1
  t=0 0
  s=No Name 
  a=tool:libavformat 52.23.1
  m=video 10000 RTP/AVP 32
  c=IN IP4 127.0.0.1
  b=AS:104857
  m=audio 20000 RTP/AVP 14
  c=IN IP4 127.0.0.1
  b=AS:64

然后通过vlc就打开这个sdp文件,就可以播放我们发送的媒体流了。

#####    #####

谈到了媒体流的发送,我想继续延伸聊聊:我们也可以使用以前介绍过的LIVE555.COM提供的LIVE555 Media Server,来发送媒体流,很简单:可以直接下载live555MediaServer.exe,然后输入: “live555MediaServer 你的文件”,例如live555MediaServer D:\test.mpg。媒体流就发送了。然后可以使用vlc来播放,vlc rtsp://本机IP/文件名(附注:在Window里通过ipconfig可以看本机IP), 例如 vlc rtsp://131.***.**.101/D:\test.mpg。

结语:播放媒体流使用vlc或一些其他的工具就在GUI里可以简单的执行了,这篇文章最后一部分是希望给读者提供一些思路,例如使用ffmpeg,LIVE555发送,并使用不同的发送方式和接受方式。

2008年12月26日星期五

用Qprocess调用外部mplayer.exe

最简单的使用Qprocess调用外部mplayer.exe的方法,以下是一个简单的例子:

void MainWindow::showMplayer() { 
    const QString mplayerPath("D:/Download/MPlayer-1.0rc2/MPlayer-1.0rc2/mplayer.exe"); 
    QStringList args; 
    args << "D:/Documents and Settings/Project/release/test.avi"; 
    QProcess *myProcess = new QProcess; 
    myProcess->start(mplayerPath, args);
}

接下来,比较复杂,我不仅调用外部mplayer.exe的方法,而且还要将播放窗口放到Qt Widget。这时必须使用mplayer 的-wid参数,这可以将mplayer输出流重定向的指定的窗体(这里就是我们所要的Qt Widget)。同时我们也可以设定一些mplayer的参数。注意:QWidget::winId() returns an HWND not an int.所以要使用类似QString::number(reinterpret_cast<qlonglong>(wd->winId()))的语句。还有一点,mplayer的configure里的GUI必须disable,不然也无法将mplayer输出流定向到Qt Widget上。以下是一个简化的例子:

void MainWindow::showMplayer() { 
    QWidget *wd = new QWidget(this);
    const QString mplayerPath("D:/Download/MPlayer-1.0rc2/MPlayer-1.0rc2/mplayer.exe"); 
    QStringList args; 
    args << " -wid" << QString::number(reinterpret_cast<qlonglong>(wd->winId())); 
    args <<" D:/Documents and Settings/Project/release/test.avi"; 
    QProcess *myProcess = new QProcess(this); 
    myProcess->start(mplayerPath,args); 
    wd->show(); 
}

2008年12月12日星期五

利用ffmpeg和sdl库播放视频经验

首先要设定Properties for Project: 在MinGW C Linker里-->Libraries --> 加入mingw32, SDLmain, SDL, avformat, avcodec, avutil,并设定想对应的正确的Library search path,在Directories里加入所需的Include path.
然后使用http://www.dranger.com/ffmpeg/tutorial02.c上的tutorial02.c这个例子。
接下来就可以编译和Build啦,(对了,在Build artifact里Artifact Type选用Shared Library或Executable都可以 )。
最后在Command Prompt里进入debug目录输入:例如:projectname.exe examplevideo.avi 就可以播放视频了,实在很简单吧。

最后,推荐一个网站:http://www.arjanhouben.nl/SDL_ffmpeg/

2008年12月9日星期二

Ffmpeg的使用, Eclipse gdb

如果是用C++的话,然后进入Project Properties-->设置好include和lib linker。然后进行编译,如果有问题,无法编译例如avcodec.h里的内容或编译avcodec.h里的内容出错(这常常发生),那么就要点击这个project,然后点击鼠标右键选Open Declaration或按F3。进入可见#include "libavutil/avutil.h"之类的声明,注意这里的#include路径和我们在Project Properties-->设置好include路径是不同的。解决它的最好方法就是,在Project Properties-->include,多设一个路径以满足其要求,例:加上"C:\DA_SDK\ffmpeg-export-snapshot"。
gdb简单的说是一个Debug工具。
MinGW自己并不配gdb,必需自己下载,并安装。注意:必须下载一个6.6版本,或以下版本的,6.8版本的不能在Eclipse中使用,至少现在是这样的。http://sourceforge.net/project/showfiles.php?group_id=2435&package_id=20507 可以直接下载已编译的版本,直接可以使用,吧BIN的exe拷贝到MinGW的bin里就可以,也可以把include里的.h拷贝到MinGW的include里。
现在终于可以进行Debug了。选择Project按鼠标右键,选Debug As --> Open Debug Dialog -->
在Environment例如:new --> Name: PATH Value: C:\DA_SDK\ffmpeg-export-snapshot\lib_dll;%PATH%。
在Debugger里:例如:Debugger: 选MinGW gdb Debugger 在Main: GDB debugger: C:\MinGW\bin\gdb.exe,其他选项可以保持不变。
现在可以进行Debug了,可以点击Elcipse工具条上的小虫,然后进入Debug环境。



2008年12月8日星期一

Ffmpeg构建和编译 续

在ffmpeg构建和编译的过程中我也遇到了一些问题,单凭网上的帮助还是不够的,我把我的解决方案记下来,希望能帮助后来人。
当完成了我上一篇文章的所有步骤后,在MSYS中输入./configure --enable-memalign-hack,若遇到这个错误:“./configure: line 221: pr: command not foundss”
The standard MSys install doesn't come with pr. You need to get it from the coreutils package. 下载coreutils-5.97-MSYS-1.0.11-snapshot.tar并解压,将bin里的文档拷贝到C:\msys\1.0\bin里,这样这个问题就可以解决。
若我们的MSYS的make.exe 的版本例如是make3.79.exe,有在./configure后进行make可能会遇到不能运行的问题,解决这个问题的方法是升级MSYS的make.exe的版本。我这里是升级到make-3.81-MSYS-1.0.11-2版本。
如果输入./configure --enable-memalign-hack后输入make,会生成.a文档,也就是“静态库”,例如: avformat.a \ avcodec.a \ avutil.a
以下转自:http://donaldtc.blogspot.com/2007/05/ffmpeg_22.html
如果希望使用FFmpeg包含的libavcodec库开发多媒体文件处理程序,还需要编译libavcodec的dll动态链接库,编译过程和上述过程稍有差别,如下所述: 首先切换到FFmpeg的源代码目录,在开始编译前先使用"make distclean"清理上一次留下的中间文件,然后向configure脚本多传递两个参数./configure --enable-shared --disable-static --enable-memalign-hack 最后执行"make"命令就可以了。
我因为需要swscale-0.dll,所以我的configure为:
./configure --enable-shared --enable-gpl --enable-swscale --enable-memalign-hack
这个已经可以满足一般的使用。
./configure --help 后你也可以根据自己的需要调整./configure
如果你需要Building FFplay,可以参考以下说明:http://ffmpeg.arrozcru.org/wiki/index.php?title=Building_FFplay

2008年12月4日星期四

一些小问题

int snprintf(char *restrict buf, size_t n, const char * restrict format, ...);

函数说明:最多从源串中拷贝 n - 1 个字符到目标串中,然后再在后面加一个 0 。所以如果目标串的大小为 n 的话,将不会溢出。函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。

_snprintf(variable, sizeof(variable), "SDL_WINDOWID=0x%lx", winId());
//snprintf(variable, sizeof(variable), "SDL_WINDOWID=0x%lx", winId());
snprintf函数并不是标准c/c++中规定的函数,但是在许多编译器中,厂商提供了其实现的版本。
在gcc中,该函数名称就snprintf,而在VC中称为_snprintf。但是我在编译的过程中,使用_snprintf就不会出现warning,若使用snprintf则会出现warning。

qmake 不会处理.cpp文件里的Q_OBJECT,所以,如果在.cpp文件中有它的话,也会产生undefined reference to vtable for "xxx::xxx". 这时,需要先用moc xxxx.cpp生成相应的moc文件,再包含到.cpp里面去,才能解决这个问题.
要解决上面的问题
如果分开, 可能就没问题, 包括 h和 cpp 分开。在你main.cpp 最后加一行 #include "main.moc" from:http://blog.donews.com/netexe/archive/2006/02/09/720544.aspx

from: http://lists.mplayerhq.hu/pipermail/ffmpeg-user/2007-March/007669.html
The correct order is -lavformat -lavcodec -lavutil. It doesnt matter 
when you use dynamic linking, but with static libs it does, because ld
does *not* scan static libraries repeatedly, only once (that is, once
per -l option).

#include
#include // < > 代表是用.PRO INCLUDEPATH引用的
#include "mediaplayer.h" // " " 代表是在现存Project中的文档

如何在C++中调用已经被编译好的C函数?这时必须采用“混合编译”,例如:
extern "C"
{
#include
#include
}
这里调用了ffmpeg的头文件avformat.h和avcodec.h,为了解决C++不能编译C的问题,
这里必须加在extern"C"里。原因:例如函数abcd()被C编译器编译后在库中的名字为_abcd,
而C++编译器则会产生_abcd_int_int之类的名字用来支持
函数重载和类型安全连接。由于编译后的名字不同,C++程序不能直接调用C函数。
C++提供了一个C连接交换指定符号extern “C” 来解决这个问题。

2008年12月2日星期二

编译FFmpeg

MinGW: A collection of freely available and freely distributable Windows specific header files and import libraries, augmenting the GNU Compiler Collection, (GCC), and its associated tools, (GNU binutils). MinGW provides a complete Open Source programming tool set which is suitable for the development of native Windows programs that do not depend on any 3rd-party C runtime DLLs.
MSYS: A Minimal SYStem providing a POSIX compatible Bourne shell environment, with a small collection of UNIX command line tools. Primarily developed as a means to execute the configure scripts and Makefiles used to build Open Source software, but also useful as a general purpose command line interface to replace Windows cmd.exe.

详细请见:FFmpeg编译指南
http://donaldtc.blogspot.com/2007/05/ffmpeg_22.html

准备MSys+MinGW系统 -->获取FFmpeg (不用SVN方式的到直接下载一个ffmpeg-export-snapshot.tar: bare sources) --> 编译(启动MSys --> "cd /C/ffmpeg" --> ./configure --enable-memalign-hack --> make --> ... ... ) --> 也可加入对第三方库的支持, 重复编译步骤,只是加入更多的东东 ./configure --enable-static --enable-shared --enable-bla bla --enable-bla bla bla 然后 make ... ... --> 在Qt+MinGW链接,配置的工作和以前配置SDL时一样 --> ... ...

# ./configure \
'--prefix=/usr' \
'--enable-gpl' \
'--enable-shared' \
'--enable-mp3lame' \

... ...
'--disable-ffserver'
# make
# make install

在configure 不要加 --disable-ffplay 就会同时安装ffplay。
典型的 Desktop (PC) 使用 - ffplay + SDL

附加:
如何uilding ffmpeg for Windows with MSYS and MinGW(在windows里构件ffmpeg用MSYS和MinGW)。
1.先下载最新的MinGW:
http://sourceforge.net/project/showfiles.php?group_id=2435
2.下载MSYS和它的bash
3.下载最新的ffmpeg
  1. 安装 MinGW (choose “MinGW base tools” and “MinGW make”) 到 c:\mingw
  2. 安装 MSYS 到 c:\msys\1.0
  3. 在MSYS安装后,回答一下几个问题:
    Do you wish to continue with the post install? [yn ] -> y
    Do you have MinGW installed? [yn ] -> y
    Where is your MinGW installation? -> C:/mingw
  4. 将 bash-2.05b-MSYS.tar.bz2 拷到 c:\msys\1.0 and 并解压缩 (bash.exe 和 sh.exe必须放到 C:\MSYS\1.0\bin里).
    我们要这么做是因为ffmpeg’s configure script不能在MSYS自配的bash 2.0.4下工作。
  5. 解压ffmpeg
然后使用MSYS进入ffmpeg目录,执行./configure 并做一些设定,一切OK,执行make。

-->其实更本不用那么麻烦,直接下载FFMPEG的SDK就可以使用了,很方便,编译太麻烦,如果搞不定,还很浪费时间呢。
http://www.ffmpeg.com.cn/index.php/SDK_Download