目录
QQ:809205580
博客地址: http://blog.csdn.net/zjhsucceed_329
QCW(Qt自定义控件)下载地址: https://sourceforge.net/projects/qcw/files/?source=navbar
1 所需软件、源码及下载地址
VLC播放器:http://www.videolan.org/
live555-latest.tar.gz:http://www.live555.com/liveMedia/public/
ffmpeg:http://ffmpeg.org/olddownload.html、
yasm:http://yasm.tortall.net/Download.html
v4l-utils:http://www.linuxtv.org/downloads/v4l-utils/
libx264:ftp://ftp.videolan.org/pub/videolan/x264/snapshots/
2安装软件及编译
2.1 安装Windows版的VLC播放器(勾选上插件,默认已经勾选)
2.2 编译live555
root@zjh:/home/work#tar zxvf live555-latest.tar.gz
root@zjh:/home/work#cd live
root@zjh:/home/work/live#./genMakefiles linux
root@zjh:/home/work/live#make
root@zjh:/home/work/live#ls mediaServer/
live555MediaServer
2.3 编译ffmpeg
编译说明文档下载地址:http://yunpan.cn/QD8RRSPCIV4aS
2.3.1 编译yasm
2.3.2 编译v4l-utils
2.3.3 编译libx264
2.3.4 编译ffmpeg
3服务器程序
3.1 源码
encoding.c
#include<math.h>
#include<libavutil/opt.h>
#include<libavcodec/avcodec.h>
#include<libavutil/imgutils.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<errno.h>
#include<signal.h>
intstop = 0;
constchar *FIFO = "test.264";
/*
* Video encoding example
*/
staticvoid video_encode_example(const char *filename, int codec_id)
{
AVCodec *codec;
AVCodecContext *c= NULL;
int i, ret, x, y, got_output;
FILE *f;
AVFrame *frame;
AVPacket pkt;
uint8_t endcode[] = { 0, 0, 1, 0xb7 };
printf("Encode video file %s\n",filename);
/* find the mpeg1 video encoder */
codec = avcodec_find_encoder(codec_id);
if (!codec)
{
fprintf(stderr, "Codec notfound\n");
exit(1);
}
c = avcodec_alloc_context3(codec);
if (!c)
{
fprintf(stderr, "Could notallocate video codec context\n");
exit(1);
}
/* put sample parameters */
c->bit_rate = 400000;
/* resolution must be a multiple of two */
c->width = 352;
c->height = 288;
/* frames per second */
c->time_base= (AVRational){1,25};
c->gop_size = 10; /* emit one intraframe every ten frames */
c->max_b_frames=1;
c->pix_fmt = AV_PIX_FMT_YUV420P;
if(codec_id == AV_CODEC_ID_H264)
av_opt_set(c->priv_data,"preset", "slow", 0);
/* open it */
if (avcodec_open2(c, codec, NULL) < 0)
{
fprintf(stderr, "Could not opencodec\n");
exit(1);
}
f = fopen(filename, "w");
if (!f)
{
fprintf(stderr, "Could not open%s\n", filename);
exit(1);
}
frame = avcodec_alloc_frame();
if (!frame)
{
fprintf(stderr, "Could notallocate video frame\n");
exit(1);
}
frame->format = c->pix_fmt;
frame->width = c->width;
frame->height = c->height;
/* the image can be allocated by any meansand av_image_alloc() is
* just the most convenient way ifav_malloc() is to be used */
ret = av_image_alloc(frame->data,frame->linesize, c->width, c->height, c->pix_fmt, 32);
if (ret < 0)
{
fprintf(stderr, "Could notallocate raw picture buffer\n");
exit(1);
}
/* encode time second of video */
i = 0;
while (!stop)
{
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by theencoder
pkt.size = 0;
fflush(stdout);
/* prepare a dummy image */
/* Y */
for(y=0;y<c->height;y++) {
for(x=0;x<c->width;x++) {
frame->data[0][y *frame->linesize[0] + x] = x + y + i * 3;
}
}
/* Cb and Cr */
for(y=0;y<c->height/2;y++) {
for(x=0;x<c->width/2;x++) {
frame->data[1][y *frame->linesize[1] + x] = 128 + y + i * 2;
frame->data[2][y *frame->linesize[2] + x] = 64 + x + i * 5;
}
}
frame->pts = i;
/* encode the image */
ret = avcodec_encode_video2(c,&pkt, frame, &got_output);
if (ret < 0) {
fprintf(stderr, "Errorencoding frame\n");
exit(1);
}
if (got_output) {
printf("Write frame %3d (size=%5d)\n",i, pkt.size);
fwrite(pkt.data, 1, pkt.size, f);
av_free_packet(&pkt);
}
i++;
}
/* get the delayed frames */
for (got_output = 1; got_output; i++) {
fflush(stdout);
ret = avcodec_encode_video2(c,&pkt, NULL, &got_output);
if (ret < 0) {
fprintf(stderr, "Errorencoding frame\n");
exit(1);
}
if (got_output) {
printf("Write frame %3d(size=%5d)\n", i, pkt.size);
fwrite(pkt.data, 1, pkt.size, f);
av_free_packet(&pkt);
}
}
/* add sequence end code to have a realmpeg file */
fwrite(endcode, 1, sizeof(endcode), f);
fclose(f);
avcodec_close(c);
av_free(c);
av_freep(&frame->data[0]);
avcodec_free_frame(&frame);
printf("\n");
}
voidhandle(int sig)
{
if (sig == SIGINT)
stop = 1;
}
intmain(int argc, char **argv)
{
signal(SIGINT, handle);
signal(SIGPIPE, SIG_IGN);
/* register all the codecs */
avcodec_register_all();
if (mkfifo(FIFO, 0644)< 0)
{
if (EEXIST != errno)
{
perror("mkfifo");
exit(1);
}
}
video_encode_example(FIFO,AV_CODEC_ID_H264);
return 0;
}
3.2 编译步骤
将encoding.c拷贝到ffmpeg源码目录的ffmpeg-1.1/doc/examples目录下,进入该目录,修改Makefile
EXAMPLES= decoding_encoding \
demuxing \
filtering_video \
filtering_audio \
metadata \
muxing \
resampling_audio \
scaling_video \
encoding
然后执行make将生成可执行文件encoding
4 html页面源码
vod.html
<!DOCTYPEhtml PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml" >
<head>
<metahttp-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script>
var itemId = 0;
function getVLC(name)
{
if(window.document[name])
{
returnwindow.document[name];
}
if(navigator.appName.indexOf("Microsoft Internet")== -1)
{
if (document.embeds&& document.embeds[name])
return document.embeds[name];
}
else
{
returndocument.getElementById(name);
}
}
function doAddPlaylist()
{
var vlc =getVLC("vlc");
itemId=vlc.playlist.add("rtsp://192.168.230.141/test.264");
document.getElementById("btn_stop").disabled= false;
}
</script>
</head>
<bodyοnlοad="doAddPlaylist()">
<div>
<objectclassid="clsid:9be31822-fdad-461b-ad51-be1d1c159921"
width="352"
height="288"
id="vlc"
events="true">
<paramname="mrl" value="rtsp://192.168.230.141/test.264" />
<paramname="showdisplay" value="true" />
<paramname="autoloop" value="false" />
<paramname="autoplay" value="false" />
<paramname="volume" value="50" />
<paramname="starttime" value="0" />
<embedpluginspage="http://www.videolan.org"
type="application/x-vlc-plugin"
version="videolan.vlcplugin.2"
width="352"
height="288"
name="vlc">
</embed>
</object>
</div>
</body>
</html>
5 运行
在Linux系统中创建工作目录
root@zjh:/home/work#mkdir video
root@zjh:/home/work#cd video/
拷贝上面编译生成的live555MediaServer到当前目录
root@zjh:/home/work/video#cp /home/work/live/mediaServer/live555MediaServer .
拷贝上面编译生成的encoding到当前目录
root@zjh:/home/work/video#cp /home/work/ffmpeg-1.1/doc/examples/encoding .
运行encoding
root@zjh:/home/work/video#./encoding
Encodevideo file test.264
[libx264@ 0x8bcf020] using cpu capabilities: MMX2 SSE2Fast SSSE3 FastShuffle SSE4.2 AVX
[libx264@ 0x8bcf020] profile High, level 1.3
在开一个终端,并进入到/home/work/video目录,运行live555MediaServer
root@zjh:/home/work/video#./live555MediaServer
LIVE555Media Server
version 0.78 (LIVE555 Streaming Medialibrary version 2013.12.16).
Playstreams from this server using the URL
rtsp://192.168.230.141/<filename>
where<filename> is a file present in the current directory.
Eachfile's type is inferred from its name suffix:
".264" => a H.264 VideoElementary Stream file
".aac" => an AAC Audio(ADTS format) file
".ac3" => an AC-3 Audiofile
".amr" => an AMR Audiofile
".dv" => a DV Video file
".m4e" => a MPEG-4 VideoElementary Stream file
".mkv" => a Matroskaaudio+video+(optional)subtitles file
".mp3" => a MPEG-1 or 2Audio file
".mpg" => a MPEG-1 or 2Program Stream (audio+video) file
".ts" => a MPEG TransportStream file
(a ".tsx" indexfile - if present - provides server 'trick play' support)
".vob" => a VOB (MPEG-2video with AC-3 audio) file
".wav" => a WAV Audio file
".webm" => a WebMaudio(Vorbis)+video(VP8) file
Seehttp://www.live555.com/mediaServer/ for additional documentation.
(Weuse port 80 for optional RTSP-over-HTTP tunneling, or for HTTP live streaming(for indexed Transport Stream files only).)
将vod.html中的IP修改为上面的红色部分,双击vod.html
单击播放按钮(将鼠标停靠在播放器窗口里就会出现控制按钮)
现在已经开始实时监控了。只不过服务器程序发来的只是简单的手动制作的图像。对encoding.c稍加修改,添加v4l2相关代码,就可以实现对摄像头的实时视频监控。