现在的位置: 首页 > 综合 > 正文

基于Linux电视棒实现DLNA和airplay功能

2013年04月15日 ⁄ 综合 ⁄ 共 10936字 ⁄ 字号 评论关闭

出发点:Android电视棒实现DLNA功能采用JAVA版本的cyberlink的话,缺点明显,SSDP协议设备发现有延时(有时还发现不了设备)体验差,基于Linux电视棒可以控制硬件成本在100元以下,而且c语言实现的cyberlink DLNA协议栈不存在设备发现不了的情况,本文记录记录linux下实现dlna碰到的一揽子问题

1. DLNA的DMR方案

方案1: MediaGateForCC (http://www.cybergarage.org/twiki/bin/view/Main/MediaGateForCC) 交叉编译,基于gstreamer实现播放器

Cyberlink协议栈需要依赖xml库, 可以选择xerces和libxml2, xerces是apatch提供的一个比较庞大的xml解析库,嵌入式设备不考虑。 

1) 编译libxml2

./configure --prefix=/home/work/mylib --host=mips-linux-gnu --build=i686 --target=mips-linux-gnu CC=mips-linux-gnu-gcc -EL CFLAGS=-I/home/work/mylib/include LDFLAGS=-L/home/work/mylib/lib

2)编译MediaGateForCC

 ./configure --prefix=/home/work/mylib --host=mips-linux-gnu --build=i686 --target=mips-linux-gnu CC=mips-linux-gnu-gcc -EL --enable-libxml2 CFLAGS=-I/home/work/mylib/include CPPFLAGS=-I/home/work/mylib/include LDFLAGS=-L/home/work/mylib/lib 

错误1:LibXml2Parser.cpp中Node *newChildNode = convertToCLinkFormat( doc, child, depth  1)改成Node *newChildNode = convertToCLinkFormat( doc, child, depth );

错误2:ControlPoint.cpp中Device **dev = new (Device(*[devCnt])); 改成 Device **dev = new Device* [devCnt];

编译成功

3) CyberLink中没有实现Media Renderer的AVTransport和RenderingControl服务,以下是补充的AVTransport..h和RenderingControl.h

class AVT : public ActionListener, public QueryListener
{

	CyberUtil::Mutex mutex;
	int maxConnectionID;

	
	////////////////////////////////////////////////
	// Constants
	////////////////////////////////////////////////

public:

	static const char *DESCRIPTION;

	static const char *SERVICE_TYPE;

	static const char * TRANSPORTSTATE ;
	static	const char *  TRANSPORTSTATUS ;
	static	const char *  PLAYBACKSTORAGEMEDIUM;
	static	const char *  RECORDSTORAGEMEDIUM;
	static	const char *  POSSIBLEPLAYBACKSTORAGEMEDIA;
	static	const char *  POSSIBLERECORDSTORAGEMEDIA;
	static	const char *  CURRENTPLAYMODE ;
	static	const char *  TRANSPORTPLAYSPEED;
	static	const char *  RECORDMEDIUMWRITESTATUS ;
	static	const char *  CURRENTRECORDQUALITYMODE ;
	static	const char *  POSSIBLERECORDQUALITYMODES;
	static	const char *  NUMBEROFTRACKS;
	static	const char *  CURRENTTRACK;
	static	const char *  CURRENTTRACKDURATION;
	static	const char *  CURRENTMEDIADURATION;
	static	const char *  CURRENTTRACKMETADATA;
	static	const char *  CURRENTTRACKURI;
	static	const char *  AVTRANSPORTURI;
	static	const char *  AVTRANSPORTURIMETADATA ;
	static	const char *  NEXTAVTRANSPORTURI;
	static	const char *  NEXTAVTRANSPORTURIMETADATA;
	static	const char *  RELATIVETIMEPOSITION;
	static	const char *  ABSOLUTETIMEPOSITION;
	static	const char *  RELATIVECOUNTERPOSITION ;
	static	const char *  ABSOLUTECOUNTERPOSITION ;
	static	const char *  CURRENTTRANSPORTACTIONS;
	static	const char *  LASTCHANGE;
	static	const char *  SETAVTRANSPORTURI;
	static	const char *  INSTANCEID;
	static	const char *  CURRENTURI;
	static	const char *  CURRENTURIMETADATA;
	static	const char *  SETNEXTAVTRANSPORTURI;
	static	const char *  NEXTURI;
	static	const char *  NEXTURIMETADATA ;
	static	const char *  GETMEDIAINFO;
	static	const char *  NRTRACKS;
	static	const char *  MEDIADURATION;
	static	const char *  PLAYMEDIUM ;
	static	const char *  RECORDMEDIUM ;
	static	const char *  WRITESTATUS ;
	static	const char *  GETTRANSPORTINFO ;
	static	const char *  CURRENTTRANSPORTSTATE;
	static	const char *  CURRENTTRANSPORTSTATUS ;
	static	const char *  CURRENTSPEED ;
	static	const char *  GETPOSITIONINFO;
	static	const char *  TRACK;
	static	const char *  TRACKDURATION;
	static	const char *  TRACKMETADATA ;
	static	const char *  TRACKURI ;
	static	const char *  RELTIME;
	static	const char *  ABSTIME;
	static	const char *  RELCOUNT;
	static	const char *  ABSCOUNT;
	static	const char *  GETDEVICECAPABILITIES;
	static	const char *  PLAYMEDIA ;
	static	const char *  RECMEDIA ;
	static	const char *  RECQUALITYMODES;
	static	const char *  GETTRANSPORTSETTINGS;
	static	const char *  PLAYMODE ;
	static	const char *  RECQUALITYMODE ;
	static	const char *  STOP;
	static	const char *  PLAY;
	static	const char *  SPEED ;
	static	const char *  PAUSE;
	static	const char *  RECORD ;
	static	const char *  SEEK ;
	static	const char *  UNIT;
	static	const char *  TARGET ;
	static	const char *  NEXT ;
	static	const char *  PREVIOUS ;
	static	const char *  SETPLAYMODE ;
	static	const char *  NEWPLAYMODE ;
	static	const char *  SETRECORDQUALITYMODE ;
	static	const char *  NEWRECORDQUALITYMODE ;
	static	const char *  GETCURRENTTRANSPORTACTIONS;
	static	const char *  ACTIONS;
	
	static	const char *  STOPPED ;
	static	const char *  PLAYING ;
	static	const char *  OK;
	static	const char *  ERROR_OCCURRED ;
	static	const char *  NORMAL ;
	static	const char *  TRACK_NR ;


	
	
	////////////////////////////////////////////////
	// Constructor 
	////////////////////////////////////////////////
	
public:

	AVT();
	
	virtual ~AVT();
	

	
public:

	void lock()
	{
		mutex.lock();
	}
	
	void unlock()
	{
		mutex.unlock();
	}
	
	////////////////////////////////////////////////
	// ConnectionID
	////////////////////////////////////////////////


	
	////////////////////////////////////////////////
	// ActionListener
	////////////////////////////////////////////////

public:

	bool actionControlReceived(Action *action);



public:

	bool queryControlReceived(StateVariable *stateVar);

};

RenderingControl服务类

class RC : public ActionListener, public QueryListener
{

	CyberUtil::Mutex mutex;
	int maxConnectionID;

	
	////////////////////////////////////////////////
	// Constants
	////////////////////////////////////////////////

public:

	static const char *DESCRIPTION;

	static const char *SERVICE_TYPE;
	
	
	static const char *PRESETNAMELIST ;
		static const char *LASTCHANGE ;
		static const char *BRIGHTNESS;
		static const char *CONTRAST ;
		static const char *SHARPNESS ;
		static const char *REDVIDEOGAIN;
		static const char *GREENVIDEOGAIN ;
		static const char *BLUEVIDEOGAIN ;
		static const char *REDVIDEOBLACKLEVEL;
		static const char *GREENVIDEOBLACKLEVEL ;
		static const char *BLUEVIDEOBLACKLEVEL ;
		static const char *COLORTEMPERATURE ;
		static const char *HORIZONTALKEYSTONE ;
		static const char *VERTICALKEYSTONE ;
		static const char *MUTE ;
		static const char *VOLUME ;
		static const char *VOLUMEDB ;
		static const char *LOUDNESS ;
		static const char *LISTPRESETS;
		static const char *INSTANCEID ;
		static const char *CURRENTPRESETNAMELIST;
		static const char *SELECTPRESET;
		static const char *PRESETNAME;
		static const char *GETBRIGHTNESS;
		static const char *CURRENTBRIGHTNESS ;
		static const char *SETBRIGHTNESS;
		static const char *DESIREDBRIGHTNESS;
		static const char *GETCONTRAST;
		static const char *CURRENTCONTRAST;
		static const char *SETCONTRAST;
		static const char *DESIREDCONTRAST;
		static const char *GETSHARPNESS;
		static const char *CURRENTSHARPNESS;
		static const char *SETSHARPNESS;
		static const char *DESIREDSHARPNESS;
		static const char *GETREDVIDEOGAIN;
		static const char *CURRENTREDVIDEOGAIN;
		static const char *SETREDVIDEOGAIN;
		static const char *DESIREDREDVIDEOGAIN ;
		static const char *GETGREENVIDEOGAIN;
		static const char *CURRENTGREENVIDEOGAIN;
		static const char *SETGREENVIDEOGAIN ;
		static const char *DESIREDGREENVIDEOGAIN ;
		static const char *GETBLUEVIDEOGAIN ;
		static const char *CURRENTBLUEVIDEOGAIN ;
		static const char *SETBLUEVIDEOGAIN;
		static const char *DESIREDBLUEVIDEOGAIN ;
		static const char *GETREDVIDEOBLACKLEVEL ;
		static const char *CURRENTREDVIDEOBLACKLEVEL ;
		static const char *SETREDVIDEOBLACKLEVEL;
		static const char *DESIREDREDVIDEOBLACKLEVEL;
		static const char *GETGREENVIDEOBLACKLEVEL;
		static const char *CURRENTGREENVIDEOBLACKLEVEL;
		static const char *SETGREENVIDEOBLACKLEVEL;
		static const char *DESIREDGREENVIDEOBLACKLEVEL;
		static const char *GETBLUEVIDEOBLACKLEVEL;
		static const char *CURRENTBLUEVIDEOBLACKLEVEL;
		static const char *SETBLUEVIDEOBLACKLEVEL;
		static const char *DESIREDBLUEVIDEOBLACKLEVEL;
		static const char *GETCOLORTEMPERATURE ;
		static const char *CURRENTCOLORTEMPERATURE;
		static const char *SETCOLORTEMPERATURE;
		static const char *DESIREDCOLORTEMPERATURE;
		static const char *GETHORIZONTALKEYSTONE;
		static const char *CURRENTHORIZONTALKEYSTONE;
		static const char *SETHORIZONTALKEYSTONE;
		static const char *DESIREDHORIZONTALKEYSTONE;
		static const char *GETVERTICALKEYSTONE;
		static const char *CURRENTVERTICALKEYSTONE;
		static const char *SETVERTICALKEYSTONE;
		static const char *DESIREDVERTICALKEYSTONE;
		static const char *GETMUTE ;
		static const char *CHANNEL;
		static const char *CURRENTMUTE ;
		static const char *SETMUTE;
		static const char *DESIREDMUTE;
		static const char *GETVOLUME;
		static const char *CURRENTVOLUME ;
		static const char *SETVOLUME ;
		static const char *DESIREDVOLUME ;
		static const char *GETVOLUMEDB ;
		static const char *SETVOLUMEDB;
		static const char *GETVOLUMEDBRANGE ;
		static const char *MINVALUE;
		static const char *MAXVALUE;
		static const char *GETLOUDNESS ;
		static const char *CURRENTLOUDNESS;
		static const char *SETLOUDNESS ;
		static const char *DESIREDLOUDNESS;
		
		static const char *MASTER ;
		static const char *FACTORYDEFAULTS ;

	
	
	
public:

	RC();
	
	virtual ~RC();
	

	
public:

	void lock()
	{
		mutex.lock();
	}
	
	void unlock()
	{
		mutex.unlock();
	}
	
	////////////////////////////////////////////////
	// ConnectionID
	////////////////////////////////////////////////



public:

	bool actionControlReceived(Action *action);



public:

	bool queryControlReceived(StateVariable *stateVar);

};

4)MediaRender的实现

MediaRender主要是实现ConnectionManager、AVTransport和RenderingControl服务

class MP : public Device
{

	CM *conMan;
	AVT *avTrans;
	RC *renderCon;

	////////////////////////////////////////////////
	// Constants
	////////////////////////////////////////////////
	
public:

	static const char *DEVICE_TYPE;

	static const int DEFAULT_HTTP_PORT;
	
	static const char *DESCRIPTION;

	////////////////////////////////////////////////
	// Constructor
	////////////////////////////////////////////////
	
public:
	
	MP();

	~MP();
	
	////////////////////////////////////////////////
	//	setName
	////////////////////////////////////////////////
	
public:

	void setName(const char *name)
	{
		setFriendlyName(name);
	}
	
	const char *getName()
	{
		getFriendlyName();
	}

	////////////////////////////////////////////////
	// Memeber
	////////////////////////////////////////////////
	
public:

	CM *getConnectionManager()
	{
		return conMan;
	}

	AVT *getAVTransport()
	{
		return avTrans;
	}
	RC *getRenderingControl()
	{
		return renderCon;
	}
	////////////////////////////////////////////////
	//	ContentDirectory	
	////////////////////////////////////////////////



public:

	void setInterfaceAddress(const char *ifaddr)
	{
		CyberNet::SetHostInterface(ifaddr);
	}

	const char *getInterfaceAddress()
	{
		return CyberNet::GetHostInterface();
	}			

	////////////////////////////////////////////////
	// HttpRequestListner (Overridded)
	////////////////////////////////////////////////

public:

	void httpRequestRecieved(CyberHTTP::HTTPRequest *httpReq);

	////////////////////////////////////////////////
	// start/stop (Overided)
	////////////////////////////////////////////////
	
public:

	bool start()
	{
	
		Device::start();
		return true;
	}
	
	bool stop()
	{
		
		Device::stop();
		return true;
	}


};

MP::MP() : Device()
{
	// Device Configuration
	loadDescription(MP::DESCRIPTION);

	// Netwroking initialization		
	UPnP::SetEnable(UPnP::USE_ONLY_IPV4_ADDR);
	string firstIf;
	GetHostAddress(0, firstIf);
	setInterfaceAddress(firstIf.c_str());
	setHTTPPort(DEFAULT_HTTP_PORT);

	// Servce Configuration
	conMan = new CM();

	Service *servConMan = getService(CM::SERVICE_TYPE);
	servConMan->loadSCPD(CM::DESCRIPTION);
	servConMan->setActionListener(getConnectionManager());
	servConMan->setQueryListener(getConnectionManager());


	avTrans= new AVT();

	Service *servAvt = getService(AVT::SERVICE_TYPE);
	servAvt->loadSCPD(AVT::DESCRIPTION);
	servAvt->setActionListener(getAVTransport());
	servAvt->setQueryListener(getAVTransport());


	
	renderCon= new RC();

	Service *servRC = getService(RC::SERVICE_TYPE);
	servRC->loadSCPD(RC::DESCRIPTION);
	servRC->setActionListener(getRenderingControl());
	servRC->setQueryListener(getRenderingControl());

	
}

5) 启动MeidaRender

int main(int argc, char* argv[])
{
MP mplayer;
	Debug::on();

	PrintMessage();

	//MediaPlayer mplayer;

	mplayer.start();
/*
#if !defined(WIN32) || defined(__CYGWIN__)
	kbinit();
#endif
*/
	int ch;
	do
	{
#if defined(WIN32) && !defined(__CYGWIN__)
		ch = getch();
#else
		ch = getchar();
#endif
		ch = toupper( ch );
		//if (ch == 'P')
			//PrintMediaServers(&mplayer);
	} while( ch != 'Q');

/*#if !defined(WIN32) || defined(__CYGWIN__)
	kbexit();
#endif
*/
	mplayer.stop();

	return 0;
}

6)性能对比测试

在Mstar的mips处理器上运行后,设备发现速度比JAVA版本cyberlink要快,通过Intel的测试工具(Intel AV Media Controller)能快速发现到设备

抱歉!评论已关闭.