出发点: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)能快速发现到设备