代碼和編程有什么區別,關于Platinum庫的MediaRender具體C++代碼實現探討

 2023-12-07 阅读 28 评论 0

摘要:接上篇博文?NDK下 將Platinum SDK 編譯成so庫 (android - upnp) 講述了如何利用該代碼庫編譯給android程序調用的so庫,其中也提到了,在使用sample-upnp工程來測試生成的so庫是無效的 大家比對一下Platinum開發庫的Platinum\Source\Platform\Andro

接上篇博文?NDK下 將Platinum SDK 編譯成so庫 (android - upnp)

講述了如何利用該代碼庫編譯給android程序調用的so庫,其中也提到了,在使用sample-upnp工程來測試生成的so庫是無效的

大家比對一下Platinum開發庫的Platinum\Source\Platform\Android\module\platinum\jni\platinum-jni.cpp

Platinum\Source\Tests\MediaRenderer\MediaRendererTest.cpp

代碼和編程有什么區別。

platinum-jni.cpp

?

#include <assert.h>
#include <jni.h>
#include <string.h>
#include <sys/types.h>#include "platinum-jni.h"
#include "Platinum.h"#include <android/log.h>/*----------------------------------------------------------------------
|   logging
+---------------------------------------------------------------------*/
NPT_SET_LOCAL_LOGGER("platinum.android.jni")/*----------------------------------------------------------------------
|   functions
+---------------------------------------------------------------------*/
__attribute__((constructor)) static void onDlOpen(void)
{
}/*----------------------------------------------------------------------
|    JNI_OnLoad
+---------------------------------------------------------------------*/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{NPT_LogManager::GetDefault().Configure("plist:.level=FINE;.handlers=ConsoleHandler;.ConsoleHandler.outputs=2;.ConsoleHandler.colors=false;.ConsoleHandler.filter=59");return JNI_VERSION_1_4;
}/** Class:     com_plutinosoft_platinum_UPnP* Method:    _init* Signature: ()J*/
JNIEXPORT jlong JNICALL Java_com_plutinosoft_platinum_UPnP__1init(JNIEnv *env, jclass)
{NPT_LOG_INFO("init");PLT_UPnP* self = new PLT_UPnP();return (jlong)self;
}/** Class:     com_plutinosoft_platinum_UPnP* Method:    _start* Signature: (J)I*/
JNIEXPORT jint JNICALL Java_com_plutinosoft_platinum_UPnP__1start(JNIEnv *, jclass, jlong _self)
{NPT_LOG_INFO("start");PLT_UPnP* self = (PLT_UPnP*)_self;return self->Start();
}/** Class:     com_plutinosoft_platinum_UPnP* Method:    _stop* Signature: (J)I*/
JNIEXPORT jint JNICALL Java_com_plutinosoft_platinum_UPnP__1stop(JNIEnv *, jclass, jlong _self)
{NPT_LOG_INFO("stop");PLT_UPnP* self = (PLT_UPnP*)_self;return self->Stop();
}

?


opencv庫、
MediaRendererTest.cpp

?

#include "PltUPnP.h"
#include "PltMediaRenderer.h"#include <stdlib.h>/*----------------------------------------------------------------------
|   globals
+---------------------------------------------------------------------*/
struct Options {const char* friendly_name;
} Options;/*----------------------------------------------------------------------
|   PrintUsageAndExit
+---------------------------------------------------------------------*/
static void
PrintUsageAndExit(char** args)
{fprintf(stderr, "usage: %s [-f <friendly_name>]\n", args[0]);fprintf(stderr, "-f : optional upnp server friendly name\n");fprintf(stderr, "<path> : local path to serve\n");exit(1);
}/*----------------------------------------------------------------------
|   ParseCommandLine
+---------------------------------------------------------------------*/
static void
ParseCommandLine(char** args)
{const char* arg;char**      tmp = args+1;/* default values */Options.friendly_name = NULL;while ((arg = *tmp++)) {if (!strcmp(arg, "-f")) {Options.friendly_name = *tmp++;} else {fprintf(stderr, "ERROR: too many arguments\n");PrintUsageAndExit(args);}}
}/*----------------------------------------------------------------------
|   main
+---------------------------------------------------------------------*/
int
main(int /* argc */, char** argv)
{   PLT_UPnP upnp;/* parse command line */ParseCommandLine(argv);PLT_DeviceHostReference device(new PLT_MediaRenderer(Options.friendly_name?Options.friendly_name:"Platinum Media Renderer",false,"e6572b54-f3c7-2d91-2fb5-b757f2537e21"));upnp.AddDevice(device);bool added = true;upnp.Start();char buf[256];while (gets(buf)) {if (*buf == 'q')break;if (*buf == 's') {if (added) {upnp.RemoveDevice(device);} else {upnp.AddDevice(device);}added = !added;}}upnp.Stop();return 0;
}

?

?

可以看出JNI接口中的PLT_UPnP對象并沒有加入PLT_DeviceHostReference對象,所以無法啟動設備,只要參照MediaRenderTest.cpp的做法我們就可以實現一個dmr設備的開啟與關閉了,童鞋們可以仿照博文?基于Platinum庫的DMR實現(android)當中的jni類來嘗試實現一下這兩個接口

jdbcutils工具類。???public?static?native?int?startMediaRender(byte[]?friendname?,byte[]?uuid);

? public?static?native?int?stopMediaRender();??

完成這一步,DMR的實現就已經成功一半了


?

java刪庫代碼?接下來我們要做的兩件事就是

1.將外部的action事件通過反射機制拋給java層處理

2.通過jni將一些事件狀態值更新至所在服務列表

?

?

刪庫命令代碼。先看第一點,每當有action事件到來時,PLT_MediaRenderer的

virtual?NPT_Result?OnAction(PLT_ActionReference&action,const?PLT_HttpRequestContext&?context);方法就會被調用

?

NPT_Result
PLT_MediaRenderer::OnAction(PLT_ActionReference&          action, const PLT_HttpRequestContext& context)
{NPT_COMPILER_UNUSED(context);/* parse the action name */NPT_String name = action->GetActionDesc().GetName();// since all actions take an instance ID and we only support 1 instance// verify that the Instance ID is 0 and return an error here now if notNPT_String serviceType = action->GetActionDesc().GetService()->GetServiceType();if (serviceType.Compare("urn:schemas-upnp-org:service:AVTransport:1", true) == 0) {if (NPT_FAILED(action->VerifyArgumentValue("InstanceID", "0"))) {action->SetError(718, "Not valid InstanceID");return NPT_FAILURE;}}serviceType = action->GetActionDesc().GetService()->GetServiceType();if (serviceType.Compare("urn:schemas-upnp-org:service:RenderingControl:1", true) == 0) {if (NPT_FAILED(action->VerifyArgumentValue("InstanceID", "0"))) {action->SetError(702, "Not valid InstanceID");return NPT_FAILURE;}}/* Is it a ConnectionManager Service Action ? */if (name.Compare("GetCurrentConnectionInfo", true) == 0) {return OnGetCurrentConnectionInfo(action);}  /* Is it a AVTransport Service Action ? */if (name.Compare("Next", true) == 0) {return OnNext(action);}if (name.Compare("Pause", true) == 0) {return OnPause(action);}if (name.Compare("Play", true) == 0) {return OnPlay(action);}if (name.Compare("Previous", true) == 0) {return OnPrevious(action);}if (name.Compare("Seek", true) == 0) {return OnSeek(action);}if (name.Compare("Stop", true) == 0) {return OnStop(action);}if (name.Compare("SetAVTransportURI", true) == 0) {return OnSetAVTransportURI(action);}if (name.Compare("SetPlayMode", true) == 0) {return OnSetPlayMode(action);}/* Is it a RendererControl Service Action ? */if (name.Compare("SetVolume", true) == 0) {return OnSetVolume(action);}if (name.Compare("SetVolumeDB", true) == 0) {return OnSetVolumeDB(action);}if (name.Compare("GetVolumeDBRange", true) == 0) {return OnGetVolumeDBRange(action);}if (name.Compare("SetMute", true) == 0) {return OnSetMute(action);}// other actions rely on state variablesNPT_CHECK_LABEL_WARNING(action->SetArgumentsOutFromStateVariable(), failure);return NPT_SUCCESS;failure:action->SetError(401,"No Such Action.");return NPT_FAILURE;
}

?

?

源代碼和代碼、部分事件會由m_Delegate成員變量來處理,也就是?virtual?void?SetDelegate(PLT_MediaRendererDelegate*?delegate)?{?m_Delegate?=?delegate;?}傳進來的

所以我們只需要從PLT_MediaRendererDelegate類派生一個子類,然后將它設進PLT_MediaRenderer并實現相應的action方法并把一些需要的值反射出來即可

class PLT_MediaRendererDelegate
{
public:virtual ~PLT_MediaRendererDelegate() {}// ConnectionManagervirtual NPT_Result OnGetCurrentConnectionInfo(PLT_ActionReference& action) = 0;// AVTransportvirtual NPT_Result OnNext(PLT_ActionReference& action) = 0;virtual NPT_Result OnPause(PLT_ActionReference& action) = 0;virtual NPT_Result OnPlay(PLT_ActionReference& action) = 0;virtual NPT_Result OnPrevious(PLT_ActionReference& action) = 0;virtual NPT_Result OnSeek(PLT_ActionReference& action) = 0;virtual NPT_Result OnStop(PLT_ActionReference& action) = 0;virtual NPT_Result OnSetAVTransportURI(PLT_ActionReference& action) = 0;virtual NPT_Result OnSetPlayMode(PLT_ActionReference& action) = 0;// RenderingControlvirtual NPT_Result OnSetVolume(PLT_ActionReference& action) = 0;virtual NPT_Result OnSetVolumeDB(PLT_ActionReference& action) = 0;virtual NPT_Result OnGetVolumeDBRange(PLT_ActionReference& action) = 0;virtual NPT_Result OnSetMute(PLT_ActionReference& action) = 0;
};


?

void ActionInflect(int cmd, const char* value, const char* data)
{if (g_vm == NULL){UpnpPrintInfo("g_vm = NULL!!!");return ;}int status;JNIEnv *env = NULL;bool isAttach = false;status = g_vm->GetEnv((void **) &env, JNI_VERSION_1_6);if(status != JNI_OK) {status = g_vm->AttachCurrentThread(&env, NULL);if(status < 0) {UpnpPrintInfo("callback_handler: failed to attach , current thread, status = %d", status);return;}isAttach = true;}jstring valueString = NULL;jstring dataString = NULL;jclass inflectClass = g_inflectClass;jmethodID inflectMethod = g_methodID;if (inflectClass == NULL || inflectMethod == NULL){goto end;}//	UpnpPrintInfo("CMD = %d\nVALUE = %s\nDATA = %s",cmd, value, data);valueString = env->NewStringUTF(value);dataString = env->NewStringUTF(data);env->CallStaticVoidMethod(inflectClass, inflectMethod, cmd, valueString, dataString);env->DeleteLocalRef(valueString);env->DeleteLocalRef(dataString);end:if (env->ExceptionOccurred()){env->ExceptionDescribe();env->ExceptionClear();}if (isAttach){g_vm->DetachCurrentThread();}}

?

python封裝類、?

再看第二點,如何將事件變量值更新至服務列表

首先通過FindServiceByType方法找到urn:schemas-upnp-org:service:AVTransport:1服務,

然后通過SetStateVariable更新值即可

變量名與值對應關系大家參照dlna文檔開發即可

庫位代碼, http://download.csdn.net/detail/geniuseoe2012/4969961

?

重點看standardizeddcps\MediaServer_4?and??MediaRenderer_3下的UPnP-av-AVTransport-v3-Service-20101231.pdf文檔

?

代碼實現可以參照PLT_MediaRenderer::SetupServices()方法

庫代碼是什么。?

NPT_Result
PLT_MediaRenderer::SetupServices()
{PLT_Service* service;{/* AVTransport */service = new PLT_Service(this,"urn:schemas-upnp-org:service:AVTransport:1", "urn:upnp-org:serviceId:AVTransport","AVTransport","urn:schemas-upnp-org:metadata-1-0/AVT/");NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_AVTransportSCPD));NPT_CHECK_FATAL(AddService(service));service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f));service->SetStateVariable("A_ARG_TYPE_InstanceID", "0"); // GetCurrentTransportActionsservice->SetStateVariable("CurrentTransportActions", "Play,Pause,Stop,Seek,Next,Previous");// GetDeviceCapabilitiesservice->SetStateVariable("PossiblePlaybackStorageMedia", "NONE,NETWORK,HDD,CD-DA,UNKNOWN");service->SetStateVariable("PossibleRecordStorageMedia", "NOT_IMPLEMENTED");service->SetStateVariable("PossibleRecordQualityModes", "NOT_IMPLEMENTED");// GetMediaInfoservice->SetStateVariable("NumberOfTracks", "0");service->SetStateVariable("CurrentMediaDuration", "00:00:00");service->SetStateVariable("AVTransportURI", "");service->SetStateVariable("AVTransportURIMetadata", "");;service->SetStateVariable("NextAVTransportURI", "NOT_IMPLEMENTED");service->SetStateVariable("NextAVTransportURIMetadata", "NOT_IMPLEMENTED");service->SetStateVariable("PlaybackStorageMedium", "NONE");service->SetStateVariable("RecordStorageMedium", "NOT_IMPLEMENTED");service->SetStateVariable("RecordMediumWriteStatus", "NOT_IMPLEMENTED");// GetPositionInfoservice->SetStateVariable("CurrentTrack", "0");NPT_Result durResult = service->SetStateVariable("CurrentTrackDuration", "00:00:00");service->SetStateVariable("CurrentTrackMetadata", "");service->SetStateVariable("CurrentTrackURI", "");NPT_Result relTimeResult = service->SetStateVariable("RelativeTimePosition", "00:00:00"); service->SetStateVariable("AbsoluteTimePosition", "00:50:00");service->SetStateVariable("RelativeCounterPosition", "2147483647"); // means NOT_IMPLEMENTEDservice->SetStateVariable("AbsoluteCounterPosition", "2147483647"); // means NOT_IMPLEMENTED// disable indirect eventing for certain state variablesPLT_StateVariable* var;var = service->FindStateVariable("RelativeTimePosition");if (var) var->DisableIndirectEventing();var = service->FindStateVariable("AbsoluteTimePosition");if (var) var->DisableIndirectEventing();var = service->FindStateVariable("RelativeCounterPosition");if (var) var->DisableIndirectEventing();var = service->FindStateVariable("AbsoluteCounterPosition");if (var) var->DisableIndirectEventing();// GetTransportInfoservice->SetStateVariable("TransportState", "NO_MEDIA_PRESENT");service->SetStateVariable("TransportStatus", "OK");service->SetStateVariable("TransportPlaySpeed", "1");// GetTransportSettingsservice->SetStateVariable("CurrentPlayMode", "NORMAL");service->SetStateVariable("CurrentRecordQualityMode", "NOT_IMPLEMENTED");}{/* ConnectionManager */service = new PLT_Service(this,"urn:schemas-upnp-org:service:ConnectionManager:1", "urn:upnp-org:serviceId:ConnectionManager","ConnectionManager");NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_ConnectionManagerSCPD));NPT_CHECK_FATAL(AddService(service));service->SetStateVariable("CurrentConnectionIDs", "0");// put all supported mime types here insteadservice->SetStateVariable("SinkProtocolInfo", "http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_SP_G726,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMDRM_WMABASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPLL_BASE,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC_XAC3,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMDRM_WMVSPLL_BASE,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPML_BASE,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_ASP_L5_SO_G726,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL_XAC3,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAPRO,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN,http-get:*:video/x-ms-asf:DLNA.ORG_PN=MPEG4_P2_ASF_ASP_L4_SO_G726,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3X,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVSPML_MP3,http-get:*:video/x-ms-wmv:*,http-get:*:video/mp4:*");service->SetStateVariable("SourceProtocolInfo", "");}{/* RenderingControl */service = new PLT_Service(this,"urn:schemas-upnp-org:service:RenderingControl:1", "urn:upnp-org:serviceId:RenderingControl","RenderingControl","urn:schemas-upnp-org:metadata-1-0/RCS/");NPT_CHECK_FATAL(service->SetSCPDXML((const char*) RDR_RenderingControlSCPD));NPT_CHECK_FATAL(AddService(service));service->SetStateVariableRate("LastChange", NPT_TimeInterval(0.2f));service->SetStateVariable("Mute", "0");service->SetStateVariableExtraAttribute("Mute", "Channel", "Master");service->SetStateVariable("Volume", "100");service->SetStateVariableExtraAttribute("Volume", "Channel", "Master");service->SetStateVariable("VolumeDB", "0");service->SetStateVariableExtraAttribute("VolumeDB", "Channel", "Master");service->SetStateVariable("PresetNameList", "FactoryDefaults");}return NPT_SUCCESS;
}

?

?

至此代碼實現步驟已全部講解完畢,當然在具體實現過程中多多少少會遇到些問題

根據log信息多問問谷哥度娘,一般都能找到解決方案的

代碼怎么運行。同時在jni層轉換C++類型與java類型時一定要注意及時釋放資源,不要造成內存泄漏了

另外不要再向樓主索要源碼了,編程最重要的是思維

只有自己動手實踐了,摸索了,思考了,解決了,自身水平才會提高

否則你永遠都只能是code-farmer而無法成為code-designer

授之以魚不如授之予漁也是藍老師一貫的教學宗旨,伸手黨請自覺繞道

編程代碼。最后感謝大家的支持,我們下節課再見!

?

?

more?brilliantPlease?pay?attention?to?my?CSDN?blog?-->http://blog.csdn.net/geniuseoe2012?

代碼的功能、?






打代碼?轉載于:https://www.cnblogs.com/dyllove98/p/3157236.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/192952.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息