用Delphi编写视频广播和点播程序
陈经韬
本文目录
一:前言
二:Mpeg1文件格式
三:网络数据广播
四:服务端程序编写
五:客户端程序编写
六:后记
一:前言
本文将介绍如何用Delphi编写视频广播(DVB)和点播(VOD)程序.内容将涉及网络数据广播和Mpeg1文件格式.希望通过本文大家可以知道流行的流媒体是怎么一回事.
我们先来了解一下什么叫DVB和VOD.DVB就是视频广播,表现形式为服务端程序打开一个视频文件播放,同一个网络内的客户端程序都可以接收到,节目的播放位置由服务端控制,客户端是被动接收的,不能改变播放位置.而VOD则刚好相反,大量的视频文件放在服务端电脑上,由客户端选择播放.播放过程中可以随时改变播放进度.无论是DVB还是VOD,它们在本质上都有共同点:就是把数据还原为影像.
关于网络播放,大概有以下几种形式:一种是基于文件共享方式,这种方式我以前已经写过一篇<<用Delphi在局域网中实现网上影院>>,这里不再详述.另外一种是基于文件切割,我在<<谈Delphi编程中文件格式的应用>>也有提到,就是把一个大的文件切割成多个小文件广播出去.这两种方法都有它的致命弱点.在第一种方法里,如果文件是在光盘里面的,那么几个人一起读的话就把电脑弄死了.即使是在硬盘里面,人数一多都会导致系统变慢.第二种方法,先不说接收文件存盘再播放有延时问题,而且多个文件之间无缝切换也是很麻烦的事情.如果客户端是无盘工作站,则完全不能用.
解决上面的问题就是用流来实现.一种方法就是服务端以流的方式读取文件(关于流的操作技巧,请参阅我以前写的<<谈Delphi编程中“流”的应用>>一文),然后在数据前面添加形如以下的数据:
var
strHeader:String;
begin
strHeader:= 'HTTP/1.1 200 OK' + EOL ;
strHeader:= strHeader + 'Server: Lovejingtao Web Server/1.0.0' + EOL ;
strHeader:= strHeader + 'Content-Type: application/octet-stream' + EOL ;
strHeader:= strHeader + 'Accept-Ranges: bytes' + EOL ;
strHeader:= strHeader + 'ETag: "05fa3dd93a9bd1:889"
'+ EOL ;
strHeader:= strHeader + 'Content-Length: 1000' + EOL ;
strHeader:= strHeader + EOL ;
......
end;
客户端用系统本身带的Mediaplay来接收,接收地址象以下这种格式:http://192.168.0.1:8080.说白了,就是伪装Mediaplay Server服务端而已.
第二种方法就是本文要讲述的方法.其实这个方法与上面的是一样的.不同的是上面的格式之类是系统集成的,我们无法改变.而这种方法需要自己进行控制.
DVB的原理如下:服务端读取文件,然后向整个网络广播或者组播,客户端接收到数据后,放到内存中播放即可.点播的核心其实也是一样,也需要把数据转化为影像.我们把这个将数据还原为影像的过程称为"解码",大家经常听到的"解码器"就是这个意思,当然,解码器是有硬解码和软解码之分的.市面上有各种各样的解码器,RealPlay公司的,微软的等等.实际上很多播放软件都是调用别人的解码库而已,所以我们说豪杰公司的<<超级解霸>>很牛,因为它的解码器是自己写的.可能你也可以写一个功能跟它相近的播放器,但是我想解码器未必是可以人人都自己做的.顺便提一句
elphi带的那个Mediaplay控件是基于MCI方式的,在核心层面来说实际上只不过是调用Windows本身的API而已.
本文用的解码器是基于微软的DirectxShow开发包,由那个Memfile改写而成.已经封装成DLL形式,这样一来就可以方便的在VC,Delphi,Vb等程序中调用.共提供了23个函数给大家调用.声明如下:
unit Mpeg1DecodeDll;
interface
uses Windows;
const DllName='Mpeg1Decode.dll';
function Mpeg1Decode_Init():bool;stdcall;external DllName;
function Mpeg1Decode_OpenVideo(hWnd:Thandle;r:TRECT;iSeek
WORD=0):bool;stdcall;external DllName;
function Mpeg1Decode_PlayVideo():Bool;stdcall;external DllName;
function Mpeg1Decode_PauseVideo():Bool;stdcall;external DllName;
function Mpeg1Decode_ResumeVideo():Bool;stdcall;external DllName;
function Mpeg1Decode_StopVideo():Bool;stdcall;external DllName;
function Mpeg1Decode_CloseVideo():Bool;stdcall;external DllName;
function Mpeg1Decode_UnInit():Bool;stdcall;external DllName;
function Mpeg1Decode_SendBuf(buf
byte;lbufsize:longlong)
WORD;stdcall;external DllName;
function Mpeg1Decode_ReSizeWindowRect(r:TRect):Bool;stdcall;external DllName;
function Mpeg1Decode_SetHWND(hwnd:Thandle):Bool;stdcall;external DllName;
function Mpeg1Decode_SetNewHWND(hwnd:Thandle):Bool;stdcall;external DllName;
function Mpeg1Decode_SetWindowRect(r:Trect):Bool;stdcall;external DllName;
function Mpeg1Decode_FullScreenVideo(bFull:BOOL):Bool;stdcall;external DllName;
procedure Mpeg1Decode_About();stdcall;external Dll