注意:需要Wowza IDE来编译这个模块
Wowza扩展模块的源代码
下面是这个模块的完整源代码:import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.ArrayList; import com.wowza.wms.amf.*; import com.wowza.wms.bootstrap.Bootstrap; import com.wowza.wms.logging.WMSLoggerFactory; import com.wowza.wms.module.*; import com.wowza.wms.stream.*; import com.wowza.wms.media.model.*; import com.wowza.wms.rtp.model.*; public class ModuleIPCameraDynamicallySetAVSync extends ModuleBase { private String logPrefix = "ModuleIPCameraDynamicallySetAVSync::"; class StreamListener implements IMediaStreamActionNotify3 { private String logPrefix = "ModuleIPCameraDynamicallySetAVSync::StreamListener::"; public void onMetaData(IMediaStream stream, AMFPacket metaDataPacket) { } public void onPauseRaw(IMediaStream stream, boolean isPause, double location) { } public void onPause(IMediaStream stream, boolean isPause, double location) { } public void onPlay(IMediaStream stream, String streamName, double playStart, double playLen, int playReset) { } private int getAvsyncMethodPropertyInt(String name){ if(name.toLowerCase().equalsIgnoreCase("rtptimecode")){ return RTPStream.AVSYNCMETHODS_RTPTIMECODE; } else if(name.toLowerCase().equalsIgnoreCase("sendreport")){ return RTPStream.AVSYNCMETHODS_SENDERREPORT; } else if(name.toLowerCase().equalsIgnoreCase("systemclock")){ return RTPStream.AVSYNCMETHODS_SYSTEMCLOCK; } return RTPStream.AVSYNCMETHODS_UNKNOWN; } private int getAvsyncStreamMethod(String filePath, String streamName) { ArrayList<String> mediaCacheFiles = new ArrayList<String>(); try { FileInputStream in = new FileInputStream(filePath); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String item = ""; while ((item = br.readLine()) != null) { item = item.trim(); if (!item.startsWith("#") && item.length() > 0) { String[] parts = item.split(" "); if(parts.length==2){ String fileStreamName = parts[0].trim(); String fileSyncMethod = parts[1].trim(); if(fileStreamName.equals(streamName)){ return this.getAvsyncMethodPropertyInt(fileSyncMethod); } } } } } catch (Exception e) { WMSLoggerFactory.getLogger(null).info( this.logPrefix + "getAvsyncStreamMethod::" + e.getMessage()); } return -1; } public void onPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) { String avSyncTxtFilePath = Bootstrap .getServerHome(Bootstrap.CONFIGHOME) + "/conf/avsyncstreams.txt"; getLogger().info( this.logPrefix+"#onPublish[" + stream.getContextStr() + "]: " + streamName+" :: "+avSyncTxtFilePath); int method = this.getAvsyncStreamMethod(avSyncTxtFilePath, streamName); if(method>=0){ RTPStream rtpStream = stream.getRTPStream(); if (rtpStream != null){ getLogger().info( this.logPrefix+"#onPublish[" + stream.getContextStr() + "]: " + streamName +" set Avsync Method to "+method); rtpStream.setAVSyncMethod(method); } else{ getLogger().info( this.logPrefix+"#onPublish[" + stream.getContextStr() + "]: " + streamName +" is not RTPStream"); } } else{ getLogger().info( this.logPrefix+"#onPublish[" + stream.getContextStr() + "]: " + streamName+" is not a valid stream"); } } public void onSeek(IMediaStream stream, double location) { } public void onStop(IMediaStream stream) { } public void onUnPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) { } public void onCodecInfoVideo(IMediaStream stream, MediaCodecInfoVideo codecInfoVideo) { } public void onCodecInfoAudio(IMediaStream stream, MediaCodecInfoAudio codecInfoAudio) { } } public void onStreamCreate(IMediaStream stream) { IMediaStreamActionNotify2 actionNotify = new StreamListener(); stream.addClientListener(actionNotify); } }当publish事件被触发后,这个模块就会在avsyncstreams.txt文件中查找对应的streamName,如果找到,就获得对应的音视频同步方式,也就是AVSync参数的配置。
下面对AVSync参数做个说明:
- senderreport - 使用RTCP协议中传送的 Sender Report (SR) 数据。这是默认设置。
- rtptimecode - 假定 RTP 的时间戳 是绝对时间,用这个时间戳。
- systemclock - 使用系统时钟。
配置
- 使用Wowza IDE编译这个模块,将生成的.jar文件拷贝到Wowza的[install-dir]/lib目录下.
- 将这个模块配置到你的应用上(也可以用管理界面来配置),在[install-dir]/conf/[application]/Application.xml文件的Root/Application/Modules部分添加如下配置:
<Module> <Name>ModuleIPCameraDynamicallySetAVSync</Name> <Description>ModuleIPCameraDynamicallySetAVSync</Description> <Class>com.wowza.wms.plugin.test.module.ModuleIPCameraDynamicallySetAVSync</Class> </Module>
- 将avsyncstreams.txt文件放在[install-dir]/conf目录下.
- 按下面的格式,在avsyncstreams.txt文件中为每一路输入流配置对应的音视频同步方式:
#StreamName[space]AVSyncMethod #camera.stream syncmethod cam1.stream sendreport