注意:需要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
