如何用Tcp/ip或者udp协议进行音频或视频的进流式播放的编程资料.(50分)

  • 主题发起人 主题发起人 agangr
  • 开始时间 开始时间
天天见到这种问题.烦...给点提示给你们吧:
1:最好肯定是用DIRCTEX.上次我已经把它做成DLL和DELPHI的接口给一位朋友了.
不过上次我说到口水干了那个提问题的朋友都不理会我.最后只好给了另外一位朋友.呵呵
2:或者MEDIAPLAY SERVER原理
界面见http://go4.163.com/lovejingtao/kiss.jpg
大概是这样的:把本地文件以流的方式广播出去.接收到后加入一些控制信息发到本地端口用
MEDIAPLAY接收即可.你可能需要参考一下下面的函数:
procedure TfrmMain.sckServerClientRead(Sender: TObject;
Socket: TCustomWinSocket);
//TCP构造HTTP协议
var
strHeader:String;
begin

objSocket:=Socket.Create(Socket.SocketHandle);
objSocket:=Socket;
//赋给objSocket,以便保持连接并且发送后继数据
objSocket.Accept(objSocket.Handle);

if intHeadReceiveState=2 then

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
Socket.SendText(strHeader);
// Socket.SendStream(stmHeaderBuffer);


idudpHeader.Active :=False;
idudpData.Active :=True;
end;

end;

3:至于用共享方法也可以.但是有个致命点就是无法广播VCD光盘节目.因为大家一起读
光驱肯定拖死.但是我已经发现了一个新方法可以解决这个问题.
共享的方法当然可以在我主页上面找到

谁帮我考试我就帮他写好了.
 
jingtao?你是陈经韬吗?如果是,希望能和你联系,能不能把你的“最好肯定是用DIRCTEX.上次我已经把它做成DLL和DELPHI的接口”发给我一份,
因为我太需要了。另外,以前看你的XMas.chm(圣诞节蜂蜜)里面的例子,还是没有看明白,而且那个方法在局域网里传输会发生错误,只有两个
机器都拨上了163,它们之间通讯才没有问题,音质可以,但是延时有好几秒呢~
 
to crazycock:
呵呵.我在看书复习,就XI了.考完试再说......
如果你是做基于摄像头压缩传输的
那么请到这里下载代码
http://go3.163.com/cloudshadow/download.htm
如果用DIRCTEX做基于文件广播的
那么需要看看DIRCTEX SDK下的MEMFILE代码,它告诉你如何播放内存的内容.
不过改为网络传输的时候需要注意以下一些问题:
1:DIRCTEX启动时会造成阻塞,所以在启动DIRCTEX时先停止传输数据,启动完后再继续传输,
否则会造成数据丢失.
2:发送头的时候.必须发两次.就是比如说发64KB,然后再回去读.这个跟播放本地内存有很大
不同.特别要注意.
 
给个修改后的memfile.h你看看吧.
这个问题我只能回答到这里了.SORRY
#include <dshow.h>
#include <streams.h>
#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>

class CMemStream : public CAsyncStream
{
public:
CMemStream(LPBYTE pbData, LONGLONG llLength, DWORD dwKBPerSec = INFINITE) :
m_pbData(pbData),
m_llLength(llLength),
m_rllPosition(0),
m_dwKBPerSec(dwKBPerSec)
{
m_dwTimeStart = timeGetTime();

clearPlayBuf();

m_packetsize = 1024*32;

m_packetnum = 32; //1M

m_playbufsize = m_packetsize * m_packetnum;

m_playbuf = new BYTE[m_playbufsize];

m_llLength = 4000000000000;

m_fileheadsize = m_packetsize * 10;

hMutex = CreateMutex(NULL,FALSE,"protect buf");

m_bheadover = FALSE;

m_breadnum = 0;

hLogFile = fopen("log.txt","w+");

}

~CMemStream()
{
clearPlayBuf();

delete m_playbuf;

fclose(hLogFile);
}

HRESULT Read(PBYTE pbBuffer,
DWORD dwBytesToRead,
BOOL bAlign,
LPDWORD pdwBytesRead)
{
CAutoLock lck(&amp;m_csLock);
DWORD dwReadLength;


dwReadLength = dwBytesToRead;

//当没有处理完播放头的时候处于等待状态
if(!m_bheadover)
{
while(m_a_fw < m_fileheadsize)
{
fprintf(hLogFile,"Wait Head/n");
Sleep(100);
}
}

m_bheadover = TRUE;


while(CanR()==false)
{
fprintf(hLogFile,"CanR=false");
Sleep(100);
}
fprintf(hLogFile,"/n");

m_rllPosition = m_a_fr % m_playbufsize;

//fprintf(hLogFile,"Read:m_rllPosition=%d/n",m_rllPosition);
//fprintf(hLogFile,"Read:m_wllPosition=%d/n/n",m_wllPosition);

//读取缓冲区数据并播放
WaitForSingleObject(hMutex,INFINITE);


CopyMemory((PVOID)pbBuffer,
(PVOID)(m_playbuf+m_rllPosition),
dwReadLength);

ReleaseMutex(hMutex);

m_a_fr += dwReadLength;

*pdwBytesRead = dwReadLength;

return S_OK;
}

bool Write(PBYTE buf)
{
if(CanW()==false)
{
fprintf(hLogFile,"CanW=false");
return false;
}
fprintf(hLogFile,"/n");

m_wllPosition = m_a_fw % m_playbufsize;

//fprintf(hLogFile,"Write:m_rllPosition=%d/n",m_rllPosition);
//fprintf(hLogFile,"Write:m_wllPosition=%d/n/n",m_wllPosition);

//添加新的数据进缓冲区
WaitForSingleObject(hMutex,INFINITE);


CopyMemory((PVOID)(m_playbuf+m_wllPosition),
(PVOID)buf,
m_packetsize);


ReleaseMutex(hMutex);

m_a_fw += m_packetsize;

return true;
}

ULONG getPacketSize()
{
return m_packetsize;
}

HRESULT SetPointer(LONGLONG llPos)
{
if (llPos < 0 || llPos > m_llLength) {
return S_FALSE;
} else
{
//关键,过滤器要对流预读,会有一次跳回0.
//害的我调试了两天,发发牢骚,哈哈~
m_a_fr = llPos;
return S_OK;
}
}

void setFileHeadSize(ULONG fileheadsize)
{
if(fileheadsize > m_packetsize *10)
{
m_fileheadsize = fileheadsize;
}else
{
m_fileheadsize = m_packetsize*10;
}
}


LONGLONG Size(LONGLONG *pSizeAvailable)
{
LONGLONG llCurrentAvailable = Int32x32To64((timeGetTime() - m_dwTimeStart),m_dwKBPerSec);
*pSizeAvailable = min(m_llLength, llCurrentAvailable);
return m_llLength;
}

void clearPlayBuf()
{
m_rllPosition = 0;

m_wllPosition = 0;
m_a_fr = 0;
m_a_fw = 0;

}

bool CanR()
{
if ((m_a_fw-m_a_fr)>= m_packetsize)
{
return true;
}else
{
return false;
}
}

bool CanW()
{
if ((m_a_fw-m_a_fr)<= (m_playbufsize-m_packetsize))
{
return true;
}else
{
return false;
}
}



DWORD Alignment()
{
return 1;
}
void Lock()
{
m_csLock.Lock();
}
void Unlock()
{
m_csLock.Unlock();
}

private:
CCritSec m_csLock;
const PBYTE m_pbData;
LONGLONG m_llLength;
DWORD m_dwKBPerSec;
DWORD m_dwTimeStart;

PBYTE m_playbuf; //自定义缓冲区
ULONG m_playbufsize;
//自定义缓冲区大小
ULONG m_packetsize; //一帧的大小
ULONG m_packetnum; //缓冲区中帧的数量
ULONG m_wllPosition;
//相对写地址
ULONG m_rllPosition;
//相对读地址
LONGLONG m_a_fr; //绝对读地址
LONGLONG m_a_fw; //绝对写地址
HANDLE hMutex; //关键段保护
ULONG m_fileheadsize; //要预读的文件头大小
BOOL m_bheadover; //时候读完头
ULONG m_breadnum; //流指针跳回0的次数
FILE *hLogFile;
};

class CMemReader : public CAsyncReader
{
public:
STDMETHODIMP Register()
{
return S_OK;
}
STDMETHODIMP Unregister()
{
return S_OK;
}
CMemReader(CMemStream *pStream, CMediaType *pmt, HRESULT *phr) :
CAsyncReader(NAME("Mem Reader"), NULL, pStream, phr)
{
m_mt = *pmt;
}
};

 
用RTSP/RTP/RTCP
看看mpeg4ip源代码也许会有收获
 
好东西,收藏
 

Similar threads

后退
顶部