使用CBaseFilter, CBaseInputPin和CBaseOutputPin写一个简单的Filter
2013-11-08 19:32
351 查看
原文地址: http://blog.csdn.net/blackboyofsnp/article/details/4877305
原文作者 : blackboycpp(AT)gmail.com
类定义:
[cpp] view
plaincopyprint?
//=============================================================================
// 名 称 : zp_Gate.h
// 功 能 : Filter, 输入Pin, 输出Pin 3个类的类定义
//
// 这几个类主要示范了如何从CBaseFilter, CBaseInputPin, CBaseOutputPin这3个
// 类派生出自已需要的Filter及Pin类. 这3个类的实现已经几乎是最简单的了, 只实现了
// 必须实现的方法. 同样地, 这个Filter的功能也相当简单, 对于数据流相当于是透明的,
// 只是简单地转发一下sample, 不进行任何操作. 它有2个Pin, 一个输入Pin, 一输出Pin,
// 这两个Pin上的数据和媒体类型当然, 也是完全一样的.
//
// 开发者: blackboycpp@gmail.com
// 更新于: 2009-11-24 15:34:54
// 备 注 :
//=============================================================================
#pragma once
// the GUID of the filter
// {1B0FFB65-DB1A-494f-8748-046970465B86}
DEFINE_GUID(CLSID_Gate,
0x1b0ffb65, 0xdb1a, 0x494f, 0x87, 0x48, 0x4, 0x69, 0x70, 0x46, 0x5b, 0x86);
class CGate;
class CDataOut;
// 功 能 : 输入Pin类
// 更新于: 2009-11-24 15:36:13
// 备 注 :
class CDataIn : public CBaseInputPin
{
friend class CDataOut;
public:
CDataIn(TCHAR* pObjName,
CGate* pFilter,
HRESULT* phr,
LPCWSTR pPinName);
virtual ~CDataIn();
public:
// 连接时检查媒体类型
HRESULT CheckMediaType(const CMediaType *pmt);
STDMETHODIMP EndOfStream();
STDMETHODIMP BeginFlush();
STDMETHODIMP EndFlush();
// 从流中接收下一个Sample
STDMETHODIMP Receive(IMediaSample *pSample);
private:
CGate* m_pGate; // 所在的Filter
};
// 功 能 : 输出Pin类
// 更新于: 2009-11-24 15:37:55
// 备 注 :
class CDataOut : public CBaseOutputPin
{
friend class CDataIn;
public:
CDataOut(TCHAR* pObjName,
CGate* pFilter,
HRESULT* phr,
LPCWSTR pPinName);
virtual ~CDataOut();
public:
// 枚举首选的媒体类型
STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum);
HRESULT CheckMediaType(const CMediaType* pmt);
HRESULT DecideBufferSize( IMemAllocator * pAlloc,
ALLOCATOR_PROPERTIES * ppropInputRequest);
HRESULT Active();
HRESULT Inactive();
// 将Sample交到下级输入Pin
HRESULT Deliver(IMediaSample* pMediaSample);
HRESULT DeliverBeginFlush();
HRESULT DeliverEndFlush();
HRESULT DeliverEndOfStream();
private:
CGate* m_pGate; // 所在的Filter
COutputQueue* m_pOutQueue;
};
class CGate : public CCritSec, public CBaseFilter
{
friend class CDataIn;
friend class CDataOut;
public:
CGate(TCHAR* pName, LPUNKNOWN pUnk, HRESULT* hr);
public:
virtual ~CGate(void);
public:
static CUnknown* WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT* phr);
CBasePin* GetPin(int n); // 获得指定Pin
int GetPinCount(); // 获得Pin数量
private:
CDataIn* m_pInputPin; // 输入Pin
CDataOut* m_pOutputPin; // 输入Pin
};
-----------------------
实现:
[cpp] view
plaincopyprint?
//=============================================================================
// 名 称 : zp_Gate.cpp
// 功 能 : CGate, CDataIn, CDataOut 3个类的实现
// 开发者: blackboycpp@gmail.com
// 更新于: 2009-11-24 16:02:17
// 备 注 :
//
//=============================================================================
#include "stdafx.h"
#include "zp_Gate.h"
//#include "zp_utl.h"
#ifdef _MANAGED
#pragma managed(push, off)
#endif
#pragma warning(disable:4355 4127)
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
&MEDIATYPE_NULL, // Major type
&MEDIASUBTYPE_NULL // Minor type
};
const AMOVIESETUP_PIN psudPins[] =
{
{
L"Input", // Pin名字字符串
FALSE, // 是否被render
FALSE, // 是否输出
FALSE, // 允许为空
FALSE, // 允许多个
&CLSID_NULL, // 连接到Filter
L"Output", // 连接到Pin
1, // 媒体类型数量
&sudPinTypes // Pin信息
},
{
L"Output",
FALSE,
TRUE,
FALSE,
FALSE,
&CLSID_NULL,
L"Input",
1,
&sudPinTypes
}
};
const AMOVIESETUP_FILTER sudGate =
{
&CLSID_Gate, // Filetr的CLSID
L"Gate", // Filter的名字
MERIT_DO_NOT_USE, // Filter的Merit
2, // Pin数量
psudPins // Pin信息
};
CFactoryTemplate g_Templates [1] =
{
{
L"Gate",
&CLSID_Gate,
CGate::CreateInstance,
NULL,
&sudGate
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return DllEntryPoint((HINSTANCE)(hModule), ul_reason_for_call, lpReserved);
}
//////////////////////////////////////////////////////////////////////////
CDataIn::CDataIn(TCHAR* pObjName,
CGate* pFilter,
HRESULT* phr,
LPCWSTR pPinName)
: CBaseInputPin(pObjName, pFilter, pFilter, phr, pPinName),
m_pGate(pFilter)
{
ASSERT(pFilter);
}
CDataIn::~CDataIn()
{
}
HRESULT CDataIn::CheckMediaType(const CMediaType *pmt)
{
CAutoLock lockit(m_pLock);
// TODO:
return NOERROR;
}
STDMETHODIMP CDataIn::EndOfStream()
{
CAutoLock lockit(m_pLock);
HRESULT hr = NOERROR;
CDataOut* pOutPin = m_pGate->m_pOutputPin;
if(pOutPin != NULL)
{
hr = pOutPin->DeliverEndOfStream();
if(FAILED(hr)) return hr;
}
return NOERROR;
}
HRESULT CDataIn::BeginFlush()
{
CAutoLock lockit(m_pLock);
// TODO:
HRESULT hr = m_pGate->m_pOutputPin->DeliverBeginFlush();
if(FAILED(hr)) return hr;
return CBaseInputPin::BeginFlush();
}
HRESULT CDataIn::EndFlush()
{
CAutoLock lockit(m_pLock);
// TODO:
HRESULT hr = m_pGate->m_pOutputPin->DeliverEndFlush();
if(FAILED(hr)) return hr;
return CBaseInputPin::EndFlush();
}
HRESULT CDataIn::Receive(IMediaSample *pSample)
{
ASSERT(pSample);
CAutoLock lockit(m_pLock);
HRESULT hr = NOERROR;
hr = CBaseInputPin::Receive(pSample);
if(FAILED(hr)) return hr;
// TODO:
hr = m_pGate->m_pOutputPin->Deliver(pSample);
if(FAILED(hr)) return hr;
return NOERROR;
}
//////////////////////////////////////////////////////////////////////////
CDataOut::CDataOut(TCHAR* pObjName,
CGate* pFilter,
HRESULT* phr,
LPCWSTR pPinName)
: CBaseOutputPin(pObjName, pFilter, pFilter, phr, pPinName),
m_pGate(pFilter)
{
ASSERT(pFilter);
m_pOutQueue = NULL;
}
CDataOut::~CDataOut()
{
}
HRESULT CDataOut::CheckMediaType(const CMediaType* pmt)
{
CAutoLock lockit(m_pLock);
// TODO:
HRESULT hr = NOERROR;
if(m_pGate->m_pInputPin->m_Connected == NULL) return VFW_E_NOT_CONNECTED;
hr = m_pGate->m_pInputPin->m_Connected->QueryAccept(pmt);
if(hr != NOERROR) return VFW_E_TYPE_NOT_ACCEPTED;
return NOERROR;
}
STDMETHODIMP CDataOut::EnumMediaTypes(IEnumMediaTypes **ppEnum)
{
CAutoLock lockit(m_pLock);
ASSERT(ppEnum);
if(m_pGate->m_pInputPin->m_Connected == NULL) return VFW_E_NOT_CONNECTED;
return m_pGate->m_pInputPin->m_Connected->EnumMediaTypes(ppEnum);
}
HRESULT CDataOut::DecideBufferSize(IMemAllocator * pAlloc,
ALLOCATOR_PROPERTIES * ppropInputRequest)
{
return NOERROR;
}
HRESULT CDataOut::Deliver(IMediaSample* pMediaSample)
{
CheckPointer(pMediaSample, E_POINTER);
// TODO:
if(m_pOutQueue == NULL) return NOERROR;
pMediaSample->AddRef();
// TODO:
return m_pOutQueue->Receive(pMediaSample);
}
HRESULT CDataOut::Active()
{
CAutoLock lockit(m_pLock);
HRESULT hr = NOERROR;
if(m_Connected == NULL) return NOERROR;
if(m_pOutQueue == NULL)
{
m_pOutQueue = new COutputQueue(m_Connected, &hr, TRUE, FALSE);
if(m_pOutQueue == NULL) return E_OUTOFMEMORY;
if(FAILED(hr))
{
delete m_pOutQueue;
m_pOutQueue = NULL;
return hr;
}
}
CBaseOutputPin::Active();
return NOERROR;
}
HRESULT CDataOut::Inactive()
{
CAutoLock lockit(m_pLock);
if(m_pOutQueue)
{
delete m_pOutQueue;
m_pOutQueue = NULL;
}
CBaseOutputPin::Inactive();
return NOERROR;
}
HRESULT CDataOut::DeliverEndOfStream()
{
if(m_pOutQueue == NULL) return NOERROR;
m_pOutQueue->EOS();
return NOERROR;
}
HRESULT CDataOut::DeliverBeginFlush()
{
if(m_pOutQueue == NULL) return NOERROR;
m_pOutQueue->BeginFlush();
return NOERROR;
}
HRESULT CDataOut::DeliverEndFlush()
{
if(m_pOutQueue == NULL) return NOERROR;
m_pOutQueue->EndFlush();
return NOERROR;
}
//////////////////////////////////////////////////////////////////////////
CUnknown* WINAPI CGate::CreateInstance(LPUNKNOWN pUnk, HRESULT* phr)
{
return new CGate(NAME("Gate"), pUnk, phr);
}
CGate::CGate(TCHAR* pName, LPUNKNOWN pUnk, HRESULT* phr) :
CBaseFilter(NAME("Gate"), pUnk, this, CLSID_Gate)
{
m_pInputPin = new CDataIn(NAME("Input Pin"), this, phr, L"Input");
m_pOutputPin = new CDataOut(NAME("Output Pin"), this, phr, L"Output");
}
CGate::~CGate()
{
if(m_pInputPin != NULL)
{
delete m_pInputPin;
}
if(m_pOutputPin != NULL)
{
delete m_pOutputPin;
}
}
CBasePin* CGate::GetPin(int n)
{
if(n < 0) return NULL;
else if(n == 0) return m_pInputPin;
else if(n == 1) return m_pOutputPin;
else return NULL;
}
int CGate::GetPinCount()
{
return 2;
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
FilterGraph里测试:
原文作者 : blackboycpp(AT)gmail.com
类定义:
[cpp] view
plaincopyprint?
//=============================================================================
// 名 称 : zp_Gate.h
// 功 能 : Filter, 输入Pin, 输出Pin 3个类的类定义
//
// 这几个类主要示范了如何从CBaseFilter, CBaseInputPin, CBaseOutputPin这3个
// 类派生出自已需要的Filter及Pin类. 这3个类的实现已经几乎是最简单的了, 只实现了
// 必须实现的方法. 同样地, 这个Filter的功能也相当简单, 对于数据流相当于是透明的,
// 只是简单地转发一下sample, 不进行任何操作. 它有2个Pin, 一个输入Pin, 一输出Pin,
// 这两个Pin上的数据和媒体类型当然, 也是完全一样的.
//
// 开发者: blackboycpp@gmail.com
// 更新于: 2009-11-24 15:34:54
// 备 注 :
//=============================================================================
#pragma once
// the GUID of the filter
// {1B0FFB65-DB1A-494f-8748-046970465B86}
DEFINE_GUID(CLSID_Gate,
0x1b0ffb65, 0xdb1a, 0x494f, 0x87, 0x48, 0x4, 0x69, 0x70, 0x46, 0x5b, 0x86);
class CGate;
class CDataOut;
// 功 能 : 输入Pin类
// 更新于: 2009-11-24 15:36:13
// 备 注 :
class CDataIn : public CBaseInputPin
{
friend class CDataOut;
public:
CDataIn(TCHAR* pObjName,
CGate* pFilter,
HRESULT* phr,
LPCWSTR pPinName);
virtual ~CDataIn();
public:
// 连接时检查媒体类型
HRESULT CheckMediaType(const CMediaType *pmt);
STDMETHODIMP EndOfStream();
STDMETHODIMP BeginFlush();
STDMETHODIMP EndFlush();
// 从流中接收下一个Sample
STDMETHODIMP Receive(IMediaSample *pSample);
private:
CGate* m_pGate; // 所在的Filter
};
// 功 能 : 输出Pin类
// 更新于: 2009-11-24 15:37:55
// 备 注 :
class CDataOut : public CBaseOutputPin
{
friend class CDataIn;
public:
CDataOut(TCHAR* pObjName,
CGate* pFilter,
HRESULT* phr,
LPCWSTR pPinName);
virtual ~CDataOut();
public:
// 枚举首选的媒体类型
STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum);
HRESULT CheckMediaType(const CMediaType* pmt);
HRESULT DecideBufferSize( IMemAllocator * pAlloc,
ALLOCATOR_PROPERTIES * ppropInputRequest);
HRESULT Active();
HRESULT Inactive();
// 将Sample交到下级输入Pin
HRESULT Deliver(IMediaSample* pMediaSample);
HRESULT DeliverBeginFlush();
HRESULT DeliverEndFlush();
HRESULT DeliverEndOfStream();
private:
CGate* m_pGate; // 所在的Filter
COutputQueue* m_pOutQueue;
};
class CGate : public CCritSec, public CBaseFilter
{
friend class CDataIn;
friend class CDataOut;
public:
CGate(TCHAR* pName, LPUNKNOWN pUnk, HRESULT* hr);
public:
virtual ~CGate(void);
public:
static CUnknown* WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT* phr);
CBasePin* GetPin(int n); // 获得指定Pin
int GetPinCount(); // 获得Pin数量
private:
CDataIn* m_pInputPin; // 输入Pin
CDataOut* m_pOutputPin; // 输入Pin
};
-----------------------
实现:
[cpp] view
plaincopyprint?
//=============================================================================
// 名 称 : zp_Gate.cpp
// 功 能 : CGate, CDataIn, CDataOut 3个类的实现
// 开发者: blackboycpp@gmail.com
// 更新于: 2009-11-24 16:02:17
// 备 注 :
//
//=============================================================================
#include "stdafx.h"
#include "zp_Gate.h"
//#include "zp_utl.h"
#ifdef _MANAGED
#pragma managed(push, off)
#endif
#pragma warning(disable:4355 4127)
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
&MEDIATYPE_NULL, // Major type
&MEDIASUBTYPE_NULL // Minor type
};
const AMOVIESETUP_PIN psudPins[] =
{
{
L"Input", // Pin名字字符串
FALSE, // 是否被render
FALSE, // 是否输出
FALSE, // 允许为空
FALSE, // 允许多个
&CLSID_NULL, // 连接到Filter
L"Output", // 连接到Pin
1, // 媒体类型数量
&sudPinTypes // Pin信息
},
{
L"Output",
FALSE,
TRUE,
FALSE,
FALSE,
&CLSID_NULL,
L"Input",
1,
&sudPinTypes
}
};
const AMOVIESETUP_FILTER sudGate =
{
&CLSID_Gate, // Filetr的CLSID
L"Gate", // Filter的名字
MERIT_DO_NOT_USE, // Filter的Merit
2, // Pin数量
psudPins // Pin信息
};
CFactoryTemplate g_Templates [1] =
{
{
L"Gate",
&CLSID_Gate,
CGate::CreateInstance,
NULL,
&sudGate
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return DllEntryPoint((HINSTANCE)(hModule), ul_reason_for_call, lpReserved);
}
//////////////////////////////////////////////////////////////////////////
CDataIn::CDataIn(TCHAR* pObjName,
CGate* pFilter,
HRESULT* phr,
LPCWSTR pPinName)
: CBaseInputPin(pObjName, pFilter, pFilter, phr, pPinName),
m_pGate(pFilter)
{
ASSERT(pFilter);
}
CDataIn::~CDataIn()
{
}
HRESULT CDataIn::CheckMediaType(const CMediaType *pmt)
{
CAutoLock lockit(m_pLock);
// TODO:
return NOERROR;
}
STDMETHODIMP CDataIn::EndOfStream()
{
CAutoLock lockit(m_pLock);
HRESULT hr = NOERROR;
CDataOut* pOutPin = m_pGate->m_pOutputPin;
if(pOutPin != NULL)
{
hr = pOutPin->DeliverEndOfStream();
if(FAILED(hr)) return hr;
}
return NOERROR;
}
HRESULT CDataIn::BeginFlush()
{
CAutoLock lockit(m_pLock);
// TODO:
HRESULT hr = m_pGate->m_pOutputPin->DeliverBeginFlush();
if(FAILED(hr)) return hr;
return CBaseInputPin::BeginFlush();
}
HRESULT CDataIn::EndFlush()
{
CAutoLock lockit(m_pLock);
// TODO:
HRESULT hr = m_pGate->m_pOutputPin->DeliverEndFlush();
if(FAILED(hr)) return hr;
return CBaseInputPin::EndFlush();
}
HRESULT CDataIn::Receive(IMediaSample *pSample)
{
ASSERT(pSample);
CAutoLock lockit(m_pLock);
HRESULT hr = NOERROR;
hr = CBaseInputPin::Receive(pSample);
if(FAILED(hr)) return hr;
// TODO:
hr = m_pGate->m_pOutputPin->Deliver(pSample);
if(FAILED(hr)) return hr;
return NOERROR;
}
//////////////////////////////////////////////////////////////////////////
CDataOut::CDataOut(TCHAR* pObjName,
CGate* pFilter,
HRESULT* phr,
LPCWSTR pPinName)
: CBaseOutputPin(pObjName, pFilter, pFilter, phr, pPinName),
m_pGate(pFilter)
{
ASSERT(pFilter);
m_pOutQueue = NULL;
}
CDataOut::~CDataOut()
{
}
HRESULT CDataOut::CheckMediaType(const CMediaType* pmt)
{
CAutoLock lockit(m_pLock);
// TODO:
HRESULT hr = NOERROR;
if(m_pGate->m_pInputPin->m_Connected == NULL) return VFW_E_NOT_CONNECTED;
hr = m_pGate->m_pInputPin->m_Connected->QueryAccept(pmt);
if(hr != NOERROR) return VFW_E_TYPE_NOT_ACCEPTED;
return NOERROR;
}
STDMETHODIMP CDataOut::EnumMediaTypes(IEnumMediaTypes **ppEnum)
{
CAutoLock lockit(m_pLock);
ASSERT(ppEnum);
if(m_pGate->m_pInputPin->m_Connected == NULL) return VFW_E_NOT_CONNECTED;
return m_pGate->m_pInputPin->m_Connected->EnumMediaTypes(ppEnum);
}
HRESULT CDataOut::DecideBufferSize(IMemAllocator * pAlloc,
ALLOCATOR_PROPERTIES * ppropInputRequest)
{
return NOERROR;
}
HRESULT CDataOut::Deliver(IMediaSample* pMediaSample)
{
CheckPointer(pMediaSample, E_POINTER);
// TODO:
if(m_pOutQueue == NULL) return NOERROR;
pMediaSample->AddRef();
// TODO:
return m_pOutQueue->Receive(pMediaSample);
}
HRESULT CDataOut::Active()
{
CAutoLock lockit(m_pLock);
HRESULT hr = NOERROR;
if(m_Connected == NULL) return NOERROR;
if(m_pOutQueue == NULL)
{
m_pOutQueue = new COutputQueue(m_Connected, &hr, TRUE, FALSE);
if(m_pOutQueue == NULL) return E_OUTOFMEMORY;
if(FAILED(hr))
{
delete m_pOutQueue;
m_pOutQueue = NULL;
return hr;
}
}
CBaseOutputPin::Active();
return NOERROR;
}
HRESULT CDataOut::Inactive()
{
CAutoLock lockit(m_pLock);
if(m_pOutQueue)
{
delete m_pOutQueue;
m_pOutQueue = NULL;
}
CBaseOutputPin::Inactive();
return NOERROR;
}
HRESULT CDataOut::DeliverEndOfStream()
{
if(m_pOutQueue == NULL) return NOERROR;
m_pOutQueue->EOS();
return NOERROR;
}
HRESULT CDataOut::DeliverBeginFlush()
{
if(m_pOutQueue == NULL) return NOERROR;
m_pOutQueue->BeginFlush();
return NOERROR;
}
HRESULT CDataOut::DeliverEndFlush()
{
if(m_pOutQueue == NULL) return NOERROR;
m_pOutQueue->EndFlush();
return NOERROR;
}
//////////////////////////////////////////////////////////////////////////
CUnknown* WINAPI CGate::CreateInstance(LPUNKNOWN pUnk, HRESULT* phr)
{
return new CGate(NAME("Gate"), pUnk, phr);
}
CGate::CGate(TCHAR* pName, LPUNKNOWN pUnk, HRESULT* phr) :
CBaseFilter(NAME("Gate"), pUnk, this, CLSID_Gate)
{
m_pInputPin = new CDataIn(NAME("Input Pin"), this, phr, L"Input");
m_pOutputPin = new CDataOut(NAME("Output Pin"), this, phr, L"Output");
}
CGate::~CGate()
{
if(m_pInputPin != NULL)
{
delete m_pInputPin;
}
if(m_pOutputPin != NULL)
{
delete m_pOutputPin;
}
}
CBasePin* CGate::GetPin(int n)
{
if(n < 0) return NULL;
else if(n == 0) return m_pInputPin;
else if(n == 1) return m_pOutputPin;
else return NULL;
}
int CGate::GetPinCount()
{
return 2;
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
FilterGraph里测试:
相关文章推荐
- 使用CBaseFilter, CBaseInputPin和CBaseOutputPin写一个简单的Filter
- 使用CBaseFilter, CBaseInputPin和CBaseOutputPin写一个简单的Filter
- 使用CBaseFilter, CBaseInputPin和CBaseOutputPin写一个简单的Filter
- Android开发之ButterKnife,GreenDao简单运用,以及推荐并使用一个好用的开源库BaseRecyclerViewAdapterHelper。
- Android开发——使用BaseAdapter做一个简单的新闻效果
- 使用C#开发一个简单的P2P应用
- 如何使用Python为Hadoop编写一个简单的MapReduce程序
- Hiredis安装使用及浅析和一个利用Hiredis实现的简单类
- 使用 jquery 的 上传文件插件 uploadify 3.1 配合 java 来做一个简单的文件上次功能。并且在界面上有radio 的选择内容也要上传
- 使用openssl实现一个简单的服务器
- Hudson--一个使用简单的构建系统
- 使用链表实现一个简单的栈
- Yii学习笔记之二(使用gii生成一个简单的样例)
- Android中编辑文本时使用TextWatcher和InputFilter.Length
- android硬编码h264数据,并使用rtp推送数据流,实现一个简单的直播-MediaCodec(一)
- 使用Node.js + MongoDB实现一个简单的日志分析系统
- 简单说明什么是递归,什么情况下会使用递归,并写一个简单的递归程序。
- 如何使用kobold2d来做一个简单的iphone游戏教程(第一部分)
- DNS浅析-Bind软件的使用及搭建一个简单的DNS缓存服务器
- c# 学习笔记之九 事件(event)的使用,一个简单例子揭示机理