最近在做一个QT的项目,实现流媒体的在线播放,是基于RTSP协议的。我们只做客户端,服务器采用的是利live555。对于音频的播放,我一开始采用的播放器是madplay,它支持音频流的在线播放。既然是播放器那么它也得要能播放视频,但是madplay是不能作为视频播放器的,所以我采用了一个linux下使用率很高的开源的播放器MPlayer。它的界面很友好,现在最新的已经是1.1版了,可以到它的官网上下载(http://www.mplayerhq.hu/design7/dload.html)。下载之后,我们对他进行编译,和普通的源码文件的编译方式一样,大体有4步,我在这里简单的说下。1.解压源码 。2.进行配置 。3.执行make。4.执行make install。当然,在这个过程中会出现一些错误,你把这些错误码复制一下,在网上都可以找到相对应的解决方法。其中可能有一个错误很棘手,我在这里也是卡了很久,就是编译时出现:
libavcodec/flashsv.c: In function 'calc_deflate_block_size':
libavcodec/flashsv.c:224:5: error: implicit declaration of function 'deflateBound' [-Werror=implicit-function-declaration]
cc1: some warnings being treated as errors
make[1]: *** [libavcodec/flashsv.o] Error 1
make[1]: Leaving directory `/home/chenyu/chenyu/MPlayer-1.1/ffmpeg'
make: *** [ffmpeg/libavcodec/libavcodec.a] 错误 2
在函数calc_deflate_block_size中,出现了deflateBound这个函数,我在flashsv.c这个文件里找到了deflateBound()这个函数,但是没有找到它的函数体,我在整个MPlayer里都没有找到,但是你会注意到flashsv.c这个文件有个头文件#include<zlib.h>,我想它应该在这个头文件中定义的,我的是zlib1.1.4,但是我在这个库里没有找到它,后来看到了一篇文章外文:
Porting to old zlib (deflateBound) & old mktemp (e.g., Red Hat Linux 9)
This message: [ Message body ] [ Respond ] [ More options ]
Related messages: [ Next message ] [ Previous message ] [ In reply to ]
From: David A. Wheeler <[email protected]>
Date: 2005-04-22 09:27:57
On Thu, 21 Apr 2005 12:19:32 -0500 Joel Schopp wrote:
>| I downloaded git-pasky 0.6.2. I cannot compile it because my zlib
>| version is 1.1.4 and git-pasky relies on functiondeflateBound()which
>| wasn't introduced until zlib version 1.2.x Is there a patch out there
>| to work around this and maybe conditionally compile based on the zlib
>| version?
>
>
Here's a quick (read: nasty, dreadful) hack to port git
to older systems like Red Hat Linux 9 which have old versions
of zlib & mktemp. Someone who actually spent two seconds
on this can no doubt give you a better solution, but it "worked for me".
Edit sha1_file.c, and change the line:
size = deflateBound(&stream, len); //既然没有它,我们可以可以用其他的语句代替它,我试了一下,可以,但是你
to //会发现这样不方便,因为下面还有很多用到的它,这样一个一个该很不方便,
size = len + 1024; /* 1024=emergency extra space */ //我们要从中找到本质的原因,这样就不会这么麻烦。我在上
//面的红色标出来了,可以看出来这是因为版本的原因,查一 //下我的zlib版本是1.1.4的,我换了一下zlib,换成了zlib1.2.7
//然后编译就不会出现上面那样的问题了。
The "deflateBound" call just finds out the maximum amount of allocation
space.
The documentation says that "deflateBound() may return a
conservative value that may be larger than /sourceLen/" in certain cases,
which worried me. So to be safe I just added a big pile of excess space
to "len";
I suspect that "size = len" is sufficient but I didn't investigate it.
If you're trying to get this to work on Red Hat Linux 9, you'll
have another problem too: old versions of "mktemp"
don't support the "-t" option. Other old distributions will
have the same problem. To find these cases, do:
grep "mktemp.*-t" *
and edit all the files to remove the "-t" option from mktemp.
That's the bare minimum to make it work; a much
cleaner solution would to specify the tempdir, e.g.,:
mktemp ${TMPDIR:-/tmp/}gitci.XXXXX
or even more portably, write the shell code to set TMPDIR to "/tmp"
locally if it's not set, then use $TMPDIR everywhere.
Not a good final solution, but enough to get started in the interim.
In long term, this should be made more portable, but it's
only ~2 weeks old after all. Some people are trying to fly this plane
to transport a buffalo herd, while others are working to attach the
wings :-).
--- David A. Wheeler
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
编译好之后生成的mplayer就可以播放视频和音频文件了,但是播放的这个视频或者音频文件是完整的在本地磁盘的。而这个QT项目的要求是实现远程数据流的播放,按照上述方法编译出来的mplay是播放不了流媒体的。你如果让他去播放live555服务器发送的媒体流,会出现 “MPEG: Missing video stream!? Contact the author, it may be a bug :( ” 这样的错误。但是前辈们为我们想到了这一点,我们可以在mplayer的官网上看到(http://www.live555.com/mplayer/)
RTSP/RTP streaming support for MPlayer
Please do the following steps, in order:
- Download and build the "LIVE555 Streaming Media" libraries. You may wish to move the resulting "live/" directory to "/usr/local/", "/usr/local/lib/", or "/usr/lib/". (Note: If you do this, you must move the entire "live/" directory - not just the library files.)
- Download the newest version of the MPlayer source code.
- If, in Step 1, you moved the "live/" directory to "/usr/local/", "/usr/local/lib/", or "/usr/lib/", run
cd MPlayer* ; ./configure
and check to see whether the "live555" library was automaticaly detected. Otherwise, run cd MPlayer* ; ./configure --extracflags=-I <path-to-LIVE555-Streaming-Media-library-directory>
- Now, build and install MPlayer as usual - i.e.,
make ; make install
(Note that you must build MPlayer with the same version of "gcc" that you used to build the LIVE555 Streaming Media code.)
按照上面的第一步先对LIVE555 Streaming Media进行编译,它的编译方法和一般的不一样,我们可以在中看到官网(http://www.live555.com/liveMedia/)给出的方法。如下:进入live目录下,执行下面的红色命令:
How to configure and build the code on Unix (including Linux, Mac OS X, QNX, and other Posix-compliant systems)
The source code package can be found (as a ".tar.gz" file) here
. Use "tar -x" and "gunzip" (or "tar -xz", if available) to extract the package; then cd to the "live" directory. Then run
./genMakefiles <os-platform> //os-platform指你的平台,我这里是写的linux
where
<os-platform>
is your target platform - e.g., "linux" or "solaris" - defined by a "config.
<os-platform>
" file. This will generate a Makefile in the "live" directory and each subdirectory.Then run "make".
- If the "make" fails, you may need to make small modifications to the appropriate "config.<os-platform>" file, and then re-run "genMakefiles <os-platform>". (E.g., you may need to add another "-I<dir>" flag to the COMPILE_OPTS definition.)
- Some people (in particular, FreeBSD users) have reported that the GNU version of "make" - often called "gmake" - works better than their default, pre-installed version of "make". (In particular, you should try using "gmake" if you encounter linking problems with the "ar" command.)
- If you're using "gcc" version 3.0 or greater: You may also wish to add the -Wno-deprecated flag to CPLUSPLUS_FLAGS.
- If no "config.<os-platform>" file exists for your target platform, then try using one of the existing files as a template.
If you wish, you can also 'install' the headers, libraries, and applications byrunning "make install".
编译好之后我们把它拷到/usr/local/lib/目录下,然后执行:
./configure --enable-live --extra-cflags="-I /usr/local/lib/live/liveMedia/include
-I /usr/local/lib/live/UsageEnvironment/include
-I /usr/local/lib/live/BasicUsageEnvironment/include
-I /usr/local/lib/live/groupsock/include"
--extra-ldflags="-L /usr/local/lib/live/liveMedia/libliveMedia.a
-L /usr/local/lib/live/UsageEnvironment/libUsageEnvironment.a
-L /usr/local/lib/live/BasicUsageEnvironment/libBasicUsageEnvironment.a
-L /usr/local/lib/live/groupsock/libgroupsock.a"
然后再执行make,在这里出现了这样的错误:
libmpdemux/demux_rtp.o: In function `demux_close_rtp':
demux_rtp.cpp:(.text+0xd6): undefined reference to `RTSPClient::teardownMediaSession(MediaSession&)'
demux_rtp.cpp:(.text+0xef): undefined reference to `Medium::close(Medium*)'
demux_rtp.cpp:(.text+0xfa): undefined reference to `Medium::close(Medium*)'
demux_rtp.cpp:(.text+0x105): undefined reference to `Medium::close(Medium*)'
demux_rtp.cpp:(.text+0x131): undefined reference to `operator delete[](void*)'
demux_rtp.cpp:(.text+0x139): undefined reference to `operator delete(void*)'
demux_rtp.cpp:(.text+0x14d): undefined reference to `UsageEnvironment::reclaim()'
demux_rtp.cpp:(.text+0x18f): undefined reference to `SIPClient::sendBYE()'
libmpdemux/demux_rtp.o: In function `demux_open_rtp':
demux_rtp.cpp:(.text+0x4df): undefined reference to `BasicTaskScheduler::createNew(unsigned int)'
demux_rtp.cpp:(.text+0x4ef): undefined reference to `BasicUsageEnvironment::createNew(TaskScheduler&)'
demux_rtp.cpp:(.text+0x548): undefined reference to `MediaSession::createNew(UsageEnvironment&, char const*)'
demux_rtp.cpp:(.text+0x560): undefined reference to `operator new(unsigned int)'
demux_rtp.cpp:(.text+0x5b8): undefined reference to `MediaSubsessionIterator::MediaSubsessionIterator(MediaSession const&)'
demux_rtp.cpp:(.text+0x5d8): undefined reference to `MediaSubsessionIterator::next()'
demux_rtp.cpp:(.text+0x624): undefined reference to `MediaSubsession::setClientPortNum(unsigned short)'
demux_rtp.cpp:(.text+0x634): undefined reference to `MediaSubsession::initiate(int)'
demux_rtp.cpp:(.text+0x73f): undefined reference to `increaseReceiveBufferTo(UsageEnvironment&, int, unsigned int)'
demux_rtp.cpp:(.text+0x7a8): undefined reference to `RTSPClient::setupMediaSubsession(MediaSubsession&, unsigned char, unsigned char, unsigned char)'
demux_rtp.cpp:(.text+0x862): undefined reference to `RTSPClient::playMediaSession(MediaSession&, double, double, float)'
demux_rtp.cpp:(.text+0x876): undefined reference to `MediaSubsessionIterator::reset()'
demux_rtp.cpp:(.text+0x8bd): undefined reference to `MediaSubsessionIterator::next()'
demux_rtp.cpp:(.text+0x8f8): undefined reference to `operator new(unsigned int)'
demux_rtp.cpp:(.text+0x990): undefined reference to `operator new(unsigned int)'
demux_rtp.cpp:(.text+0xa28): undefined reference to `MediaSubsessionIterator::~MediaSubsessionIterator()'
demux_rtp.cpp:(.text+0xab9): undefined reference to `SIPClient::sendACK()'
demux_rtp.cpp:(.text+0xaca): undefined reference to `MediaSubsessionIterator::~MediaSubsessionIterator()'
demux_rtp.cpp:(.text+0xb2b): undefined reference to `RTSPClient::createNew(UsageEnvironment&, int, char const*, unsigned short)'
demux_rtp.cpp:(.text+0xb7c): undefined reference to `RTSPClient::describeWithPassword(char const*, char const*, char const*, unsigned char, int)'
demux_rtp.cpp:(.text+0xbf8): undefined reference to `SIPClient::createNew(UsageEnvironment&, unsigned char, char const*, int, char const*)'
demux_rtp.cpp:(.text+0xc42): undefined reference to `SIPClient::inviteWithPassword(char const*, char const*, char const*)'
demux_rtp.cpp:(.text+0xcc2): undefined reference to `RTSPClient::describeURL(char const*, Authenticator*, unsigned char, int)'
demux_rtp.cpp:(.text+0xce5): undefined reference to `SIPClient::invite(char const*, Authenticator*)'
demux_rtp.cpp:(.text+0xd16): undefined reference to `MediaSubsessionIterator::~MediaSubsessionIterator()'
libmpdemux/demux_rtp.o: In function `getBuffer(demuxer*, demux_stream_t*, unsigned char, float&)':
demux_rtp.cpp:(.text+0x1666): undefined reference to `FramedSource::getNextFrame(unsigned char*, unsigned int, void (*)(void*, unsigned int, unsigned int, timeval, unsigned int), void*, void (*)(void*), void*)'
demux_rtp.cpp:(.text+0x1917): undefined reference to `FramedSource::getNextFrame(unsigned char*, unsigned int, void (*)(void*, unsigned int, unsigned int, timeval, unsigned int), void*, void (*)(void*), void*)'
libmpdemux/demux_rtp.o: In function `ReadBufferQueue::~ReadBufferQueue()':
demux_rtp.cpp:(.text+0x112b): undefined reference to `operator delete(void*)'
libmpdemux/demux_rtp.o: In function `_GLOBAL__sub_I_rtsp_transport_tcp':
demux_rtp.cpp:(.text.startup+0x7): undefined reference to `DELAY_SECOND'
demux_rtp.cpp:(.text.startup+0x1b): undefined reference to `operator*(short, DelayInterval const&)'
demux_rtp.cpp:(.text.startup+0x3a): undefined reference to `operator*(short, DelayInterval const&)'
demux_rtp.cpp:(.text.startup+0x59): undefined reference to `operator*(short, DelayInterval const&)'
libmpdemux/demux_rtp.o:(.rodata._ZTI15ReadBufferQueue[typeinfo for ReadBufferQueue]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
libmpdemux/demux_rtp.o:(.eh_frame+0xf3): undefined reference to `__gxx_personality_v0'
libmpdemux/demux_rtp_codec.o: In function `rtpCodecInitialize_video(demuxer*, MediaSubsession*, unsigned int&)':
demux_rtp_codec.cpp:(.text+0x61b): undefined reference to `operator new[](unsigned int)'
demux_rtp_codec.cpp:(.text+0x6f9): undefined reference to `operator delete[](void*)'
demux_rtp_codec.cpp:(.text+0x7a4): undefined reference to `parseGeneralConfigStr(char const*, unsigned int&)'
libmpdemux/demux_rtp_codec.o: In function `rtpCodecInitialize_audio(demuxer*, MediaSubsession*, unsigned int&)':
demux_rtp_codec.cpp:(.text+0xe77): undefined reference to `parseStreamMuxConfigStr(char const*, unsigned int&)'
demux_rtp_codec.cpp:(.text+0xe99): undefined reference to `MPEG4LATMAudioRTPSource::omitLATMDataLengthField()'
demux_rtp_codec.cpp:(.text+0xec0): undefined reference to `parseGeneralConfigStr(char const*, unsigned int&)'
collect2: ld returned 1 exit status
make: *** [mplayer] 错误 1
在这里查了好久都没有搞定,只有到live555的官网去查了,在官网的mails lists里我看到之前有人出现了和我同样的错误,原来在最新的live555里确实存在这样的一个问题,我把原文列出来:
There is a problem with some of the newer live555 libraries. Perhaps the easiest thing is to add:
to your MPlayer ./configure string or consider using an older live555 version:
Code:
wget http://live555sourcecontrol.googlecode.com/files/live.2011.12.23.tar.gz
__________________
如果你用的是最新的live555,你在配置MPlayer的时候,在./config 后加上--disable-live,也可以换成其他的旧版本的live,如:
http://live555sourcecontrol.googlecode.com/files/live.2011.12.23.tar.gz
但是这个又有个问题出来了,把参数改成--disable-live后,在编译MPlayer的时候,它就不会把live555的支持加入里面了,也就是说,编译出来的MPlayer还是不支持RTSP媒体流的播放,所以这个方法不行。
还有的是这样解释的,live555服务器是用C++写的,而MPlayer是用C写的,我们在编译到最后的时候,也就是出现 ”gcc -o mplayer ...... (后面的省略,如果你的出现错误,你会看到的,嘎嘎)“。我们把用C++写的文件包含到C写的Mplayer里,然后用gcc去编译,它是无法识别的,所以会出现那样的错误,网友提供的方法是把”gcc -o mplayer ...... ”这段编译代码复制下来,把gcc换成g++ 重新编译,可惜的是我这样试了,可是还是不行,搞得头都大了,现在把问题贴出来,求大神指教啊!!!