Created new red5 app, videoproxy and adapted VideoReceiver from bbb-bot using flazr.
TO-DO: Adapt VideoPublisher from bot Logic with url.
This commit is contained in:
parent
ce4107bf50
commit
1379f2d086
@ -41,7 +41,7 @@ import org.red5.server.stream.message.RTMPMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.red5.client.net.rtmp.RTMPClient;
|
||||
|
||||
import org.red5.client.net.rtmp.INetStreamEventHandler;
|
||||
|
||||
/**
|
||||
@ -124,7 +124,7 @@ public class StreamingProxy implements IPushableConsumer, IPipeConnectionListene
|
||||
synchronized public void pushMessage(IPipe pipe, IMessage message) throws IOException {
|
||||
if (state >= PUBLISHED && message instanceof RTMPMessage) {
|
||||
RTMPMessage rtmpMsg = (RTMPMessage) message;
|
||||
rtmpClient.publishStreamData(streamId, rtmpMsg);
|
||||
//rtmpClient.publishStreamData(streamId, rtmpMsg);
|
||||
} else {
|
||||
frameBuffer.add(message);
|
||||
}
|
||||
@ -152,10 +152,10 @@ public class StreamingProxy implements IPushableConsumer, IPipeConnectionListene
|
||||
log.debug("<:{}", code);
|
||||
if (StatusCodes.NS_PUBLISH_START.equals(code)) {
|
||||
state = PUBLISHED;
|
||||
rtmpClient.invoke("FCPublish", new Object[] { publishName }, this);
|
||||
while (frameBuffer.size() > 0) {
|
||||
rtmpClient.publishStreamData(streamId, frameBuffer.remove(0));
|
||||
}
|
||||
//rtmpClient.invoke("FCPublish", new Object[] { publishName }, this);
|
||||
//while (frameBuffer.size() > 0) {
|
||||
// rtmpClient.publishStreamData(streamId, frameBuffer.remove(0));
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ public class StreamingProxy implements IPushableConsumer, IPipeConnectionListene
|
||||
if ("connect".equals(call.getServiceMethodName())) {
|
||||
state = STREAM_CREATING;
|
||||
System.out.println("CRIANDO STREAM");
|
||||
rtmpClient.createStream(this);
|
||||
//rtmpClient.createStream(this);
|
||||
} else if ("createStream".equals(call.getServiceMethodName())) {
|
||||
System.out.println("CRIANDO STREAM 2");
|
||||
state = PUBLISHING;
|
||||
@ -183,7 +183,7 @@ public class StreamingProxy implements IPushableConsumer, IPipeConnectionListene
|
||||
Integer streamIdInt = (Integer) result;
|
||||
streamId = streamIdInt.intValue();
|
||||
log.debug("Publishing: {}", state);
|
||||
rtmpClient.publish(streamIdInt.intValue(), publishName, publishMode, this);
|
||||
//rtmpClient.publish(streamIdInt.intValue(), publishName, publishMode, this);
|
||||
} else {
|
||||
rtmpClient.disconnect();
|
||||
state = STOPPED;
|
||||
|
@ -56,6 +56,13 @@ public class VideoApplication extends MultiThreadedApplicationAdapter {
|
||||
@Override
|
||||
public boolean appConnect(IConnection conn, Object[] params) {
|
||||
log.info("oflaDemo appConnect");
|
||||
System.out.println("TESTE 2");
|
||||
System.out.println("TESTE 2");
|
||||
System.out.println("TESTE 2");
|
||||
System.out.println("TESTE 2");
|
||||
System.out.println(conn);
|
||||
System.out.println(params);
|
||||
|
||||
return super.appConnect(conn, params);
|
||||
}
|
||||
|
||||
@ -104,15 +111,15 @@ public class VideoApplication extends MultiThreadedApplicationAdapter {
|
||||
System.out.println("TESTE");
|
||||
System.out.println("TESTE");
|
||||
System.out.println("TESTE");
|
||||
IScope scope = stream.getScope();
|
||||
IBroadcastScope bsScope = getBroadcastScope(scope, stream.getPublishedName());
|
||||
StreamingProxy proxy = new StreamingProxy();
|
||||
proxy.setHost("0.0.0.0");
|
||||
proxy.setApp("video");
|
||||
proxy.setPort(1935);
|
||||
proxy.init();
|
||||
bsScope.subscribe(proxy, null);
|
||||
proxy.start("MY_STRING", StreamingProxy.LIVE, null);
|
||||
//IScope scope = stream.getScope();
|
||||
//IBroadcastScope bsScope = getBroadcastScope(scope, stream.getPublishedName());
|
||||
//StreamingProxy proxy = new StreamingProxy();
|
||||
//proxy.setHost("143.54.10.163");
|
||||
//proxy.setApp("video");
|
||||
//proxy.setPort(1935);
|
||||
//proxy.init();
|
||||
//bsScope.subscribe(proxy, null);
|
||||
//proxy.start("teste", StreamingProxy.LIVE, null);
|
||||
//streamingProxyMap.put(stream.getPublishedName(), proxy);
|
||||
//stream.addStreamListener(this);
|
||||
}
|
||||
|
131
bbb-videoproxy/build.gradle
Executable file
131
bbb-videoproxy/build.gradle
Executable file
@ -0,0 +1,131 @@
|
||||
usePlugin 'java'
|
||||
usePlugin 'war'
|
||||
usePlugin 'eclipse'
|
||||
|
||||
version = '0.7'
|
||||
jar.enabled = true
|
||||
archivesBaseName = 'videoproxy'
|
||||
|
||||
task dependencies(type: Copy) {
|
||||
into('lib')
|
||||
from configurations.default
|
||||
from configurations.default.allArtifacts*.file
|
||||
}
|
||||
|
||||
task resolveDeps(dependsOn: configurations.default.buildArtifacts, type: Copy) {
|
||||
into('lib')
|
||||
from configurations.default
|
||||
from configurations.default.allArtifacts*.file
|
||||
}
|
||||
|
||||
task resolveDependencies(dependsOn: configurations.default.buildArtifacts, type: Copy) {
|
||||
into('lib')
|
||||
from configurations.default
|
||||
from configurations.default.allArtifacts*.file
|
||||
}
|
||||
|
||||
repositories {
|
||||
add(new org.apache.ivy.plugins.resolver.ChainResolver()) {
|
||||
name = 'remote'
|
||||
returnFirst = true
|
||||
add(new org.apache.ivy.plugins.resolver.URLResolver()) {
|
||||
name = "googlecode"
|
||||
addArtifactPattern "http://red5.googlecode.com/svn/repository/[artifact](-[revision]).[ext]"
|
||||
addArtifactPattern "http://red5.googlecode.com/svn/repository/[organisation]/[artifact](-[revision]).[ext]"
|
||||
}
|
||||
add(new org.apache.ivy.plugins.resolver.URLResolver()) {
|
||||
name = "blindside-repos"
|
||||
addArtifactPattern "http://blindside.googlecode.com/svn/repository/[artifact](-[revision]).[ext]"
|
||||
addArtifactPattern "http://blindside.googlecode.com/svn/repository/[organisation]/[artifact](-[revision]).[ext]"
|
||||
}
|
||||
add(new org.apache.ivy.plugins.resolver.URLResolver()) {
|
||||
name = "maven2-central"
|
||||
m2compatible = true
|
||||
addArtifactPattern "http://repo1.maven.org/maven2/[organisation]/[module]/[revision]/[artifact](-[revision]).[ext]"
|
||||
addArtifactPattern "http://repo1.maven.org/maven2/[organisation]/[artifact]/[revision]/[artifact](-[revision]).[ext]"
|
||||
}
|
||||
add(new org.apache.ivy.plugins.resolver.URLResolver()) {
|
||||
name = "testng_ibiblio_maven2"
|
||||
m2compatible = true
|
||||
addArtifactPattern "http://repo1.maven.org/maven2/[organisation]/[module]/[revision]/[artifact](-[revision])-jdk15.[ext]"
|
||||
addArtifactPattern "http://repo1.maven.org/maven2/[organisation]/[artifact]/[revision]/[artifact](-[revision])-jdk15.[ext]"
|
||||
}
|
||||
add(new org.apache.ivy.plugins.resolver.URLResolver()) {
|
||||
name = "netty-dependency"
|
||||
m2compatible = true
|
||||
addArtifactPattern "http://repository.jboss.org/nexus/content/groups/public-jboss/[organisation]/[module]/[revision]/[artifact](-[revision]).[ext]"
|
||||
addArtifactPattern "http://repo1.maven.org/maven2/[organisation]/[artifact]/[revision]/[artifact](-[revision]).[ext]"
|
||||
}
|
||||
add(new org.apache.ivy.plugins.resolver.URLResolver()) {
|
||||
name = "spring-bundles"
|
||||
m2compatible = true
|
||||
addArtifactPattern "http://repository.springsource.com/maven/bundles/external/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
|
||||
addArtifactPattern "http://repository.springsource.com/maven/bundles/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Servlet
|
||||
providedCompile 'javax.servlet:servlet-api:2.5@jar'
|
||||
|
||||
// Mina
|
||||
providedCompile 'org.apache.mina:mina-core:2.0.7@jar'
|
||||
providedCompile 'org.apache.mina:mina-integration-beans:2.0.7@jar'
|
||||
providedCompile 'org.apache.mina:mina-integration-jmx:2.0.7@jar'
|
||||
|
||||
// Spring
|
||||
providedCompile 'org.springframework:spring-web:3.1.1.RELEASE@jar'
|
||||
providedCompile 'org.springframework:spring-beans:3.1.1.RELEASE@jar'
|
||||
providedCompile 'org.springframework:spring-context:3.1.1.RELEASE@jar'
|
||||
providedCompile 'org.springframework:spring-core:3.1.1.RELEASE@jar'
|
||||
|
||||
// Red5
|
||||
providedCompile 'org/red5:red5:1.0r4643@jar'
|
||||
compile files('./lib/flazr-git.jar')
|
||||
compile files('./lib/netty-3.2.7.Final.jar')
|
||||
|
||||
// Logging
|
||||
providedCompile 'ch.qos.logback:logback-core:1.0.9@jar'
|
||||
providedCompile 'ch.qos.logback:logback-classic:1.0.9@jar'
|
||||
providedCompile 'org.slf4j:log4j-over-slf4j:1.7.2@jar'
|
||||
providedCompile 'org.slf4j:jcl-over-slf4j:1.7.2@jar'
|
||||
providedCompile 'org.slf4j:jul-to-slf4j:1.7.2@jar'
|
||||
providedCompile 'org.slf4j:slf4j-api:1.7.2@jar'
|
||||
|
||||
// Needed for the JVM shutdown hook but needs to be put into red5/lib dir.
|
||||
// Otherwise we get exception on aop utils class not found.
|
||||
providedCompile 'org.springframework:spring-aop:3.0.6.RELEASE@jar'
|
||||
compile 'aopalliance:aopalliance:1.0@jar'
|
||||
|
||||
// Java Concurrency In Practice
|
||||
providedCompile 'net.jcip:jcip-annotations:1.0@jar'
|
||||
|
||||
// Testing
|
||||
compile 'org.testng:testng:5.8@jar'
|
||||
compile 'org.easymock:easymock:2.4@jar'
|
||||
|
||||
//redis
|
||||
compile 'redis.clients:jedis:2.0.0'
|
||||
providedCompile 'commons-pool:commons-pool:1.5.6'
|
||||
}
|
||||
|
||||
test {
|
||||
useTestNG()
|
||||
}
|
||||
|
||||
war.doLast {
|
||||
ant.unzip(src: war.archivePath, dest: "$buildDir/videoproxy")
|
||||
}
|
||||
|
||||
|
||||
task deploy() << {
|
||||
def red5AppsDir = '/usr/share/red5/webapps'
|
||||
def videoDir = new File("${red5AppsDir}/videoproxy")
|
||||
if (videoDir.exists()) ant.delete(dir: videoDir)
|
||||
ant.mkdir(dir: videoDir)
|
||||
ant.copy(todir: videoDir) {
|
||||
fileset(dir: "$buildDir/videoproxy")
|
||||
}
|
||||
}
|
||||
|
20
bbb-videoproxy/build/classes/main/logback-video.xml
Normal file
20
bbb-videoproxy/build/classes/main/logback-video.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="VIDEOPROXY" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<File>log/videoproxy.log</File>
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>log/videoproxy.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
<!-- keep 5 days worth of history -->
|
||||
<MaxHistory>5</MaxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<Pattern>%date [%thread] %-5level %logger{35} - %msg%n</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
<root>
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="VIDEOPROXY" />
|
||||
</root>
|
||||
</configuration>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bbb-videoproxy/build/libs/videoproxy-0.7.war
Normal file
BIN
bbb-videoproxy/build/libs/videoproxy-0.7.war
Normal file
Binary file not shown.
4
bbb-videoproxy/build/videoproxy/META-INF/MANIFEST.MF
Normal file
4
bbb-videoproxy/build/videoproxy/META-INF/MANIFEST.MF
Normal file
@ -0,0 +1,4 @@
|
||||
Manifest-Version: 1.0
|
||||
Ant-Version: Apache Ant 1.7.0
|
||||
Created-By: 20.0-b12 (Sun Microsystems Inc.)
|
||||
|
@ -0,0 +1,2 @@
|
||||
redis.host=127.0.0.1
|
||||
redis.port=6379
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="VIDEOPROXY" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<File>log/videoproxy.log</File>
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>log/videoproxy.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
<!-- keep 5 days worth of history -->
|
||||
<MaxHistory>5</MaxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<Pattern>%date [%thread] %-5level %logger{35} - %msg%n</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
<root>
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="VIDEOPROXY" />
|
||||
</root>
|
||||
</configuration>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bbb-videoproxy/build/videoproxy/WEB-INF/lib/aopalliance-1.0.jar
Normal file
BIN
bbb-videoproxy/build/videoproxy/WEB-INF/lib/aopalliance-1.0.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/build/videoproxy/WEB-INF/lib/easymock-2.4.jar
Normal file
BIN
bbb-videoproxy/build/videoproxy/WEB-INF/lib/easymock-2.4.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/build/videoproxy/WEB-INF/lib/flazr-git.jar
Normal file
BIN
bbb-videoproxy/build/videoproxy/WEB-INF/lib/flazr-git.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/build/videoproxy/WEB-INF/lib/jedis-2.0.0.jar
Normal file
BIN
bbb-videoproxy/build/videoproxy/WEB-INF/lib/jedis-2.0.0.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
bbb-videoproxy/build/videoproxy/WEB-INF/lib/testng-5.8.jar
Normal file
BIN
bbb-videoproxy/build/videoproxy/WEB-INF/lib/testng-5.8.jar
Normal file
Binary file not shown.
@ -0,0 +1,2 @@
|
||||
webapp.contextPath=/videoproxy
|
||||
webapp.virtualHosts=*, localhost, localhost:8088, 127.0.0.1:8088
|
57
bbb-videoproxy/build/videoproxy/WEB-INF/red5-web.xml
Normal file
57
bbb-videoproxy/build/videoproxy/WEB-INF/red5-web.xml
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||
|
||||
Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">
|
||||
|
||||
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
|
||||
<property name="locations">
|
||||
<list>
|
||||
<value>/WEB-INF/red5-web.properties</value>
|
||||
<value>/WEB-INF/bigbluebutton-video.properties</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="web.context" class="org.red5.server.Context"
|
||||
autowire="byType" />
|
||||
|
||||
<bean id="web.scope" class="org.red5.server.scope.WebScope" init-method="register">
|
||||
<property name="server" ref="red5.server" />
|
||||
<property name="parent" ref="global.scope" />
|
||||
<property name="context" ref="web.context" />
|
||||
<property name="handler" ref="web.handler" />
|
||||
<property name="contextPath" value="${webapp.contextPath}" />
|
||||
<property name="virtualHosts" value="${webapp.virtualHosts}" />
|
||||
</bean>
|
||||
|
||||
<bean id="web.handler" class="org.bigbluebutton.app.videoproxy.VideoApplication">
|
||||
<property name="recordVideoStream" value="true"/>
|
||||
<property name="eventRecordingService" ref="redisRecorder"/>
|
||||
</bean>
|
||||
|
||||
<bean id="redisRecorder" class="org.bigbluebutton.app.videoproxy.EventRecordingService">
|
||||
<constructor-arg index="0" value="${redis.host}"/>
|
||||
<constructor-arg index="1" value="${redis.port}"/>
|
||||
</bean>
|
||||
</beans>
|
56
bbb-videoproxy/build/videoproxy/WEB-INF/web.xml
Normal file
56
bbb-videoproxy/build/videoproxy/WEB-INF/web.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!--
|
||||
|
||||
BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||
|
||||
Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-->
|
||||
<web-app
|
||||
xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
|
||||
version="2.4">
|
||||
<display-name>BigBlueButton Video Proxy Application</display-name>
|
||||
|
||||
<context-param>
|
||||
<param-name>webAppRootKey</param-name>
|
||||
<param-value>/videoproxy</param-value>
|
||||
</context-param>
|
||||
|
||||
|
||||
<listener>
|
||||
<listener-class>org.red5.logging.ContextLoggingListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<filter>
|
||||
<filter-name>LoggerContextFilter</filter-name>
|
||||
<filter-class>org.red5.logging.LoggerContextFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>LoggerContextFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Forbidden</web-resource-name>
|
||||
<url-pattern>/streams/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint/>
|
||||
</security-constraint>
|
||||
|
||||
</web-app>
|
1
bbb-videoproxy/build/videoproxy/streams/README
Normal file
1
bbb-videoproxy/build/videoproxy/streams/README
Normal file
@ -0,0 +1 @@
|
||||
Do not delete the streams directory. This is where the video recordings will be saved.
|
BIN
bbb-videoproxy/lib/aopalliance-1.0.jar
Normal file
BIN
bbb-videoproxy/lib/aopalliance-1.0.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/commons-pool-1.5.6.jar
Normal file
BIN
bbb-videoproxy/lib/commons-pool-1.5.6.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/easymock-2.4.jar
Normal file
BIN
bbb-videoproxy/lib/easymock-2.4.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/flazr-git.jar
Normal file
BIN
bbb-videoproxy/lib/flazr-git.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/jcip-annotations-1.0.jar
Normal file
BIN
bbb-videoproxy/lib/jcip-annotations-1.0.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/jcl-over-slf4j-1.7.2.jar
Normal file
BIN
bbb-videoproxy/lib/jcl-over-slf4j-1.7.2.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/jedis-2.0.0.jar
Normal file
BIN
bbb-videoproxy/lib/jedis-2.0.0.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/jul-to-slf4j-1.7.2.jar
Normal file
BIN
bbb-videoproxy/lib/jul-to-slf4j-1.7.2.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/log4j-over-slf4j-1.7.2.jar
Normal file
BIN
bbb-videoproxy/lib/log4j-over-slf4j-1.7.2.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/logback-classic-1.0.9.jar
Normal file
BIN
bbb-videoproxy/lib/logback-classic-1.0.9.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/logback-core-1.0.9.jar
Normal file
BIN
bbb-videoproxy/lib/logback-core-1.0.9.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/mina-core-2.0.7.jar
Normal file
BIN
bbb-videoproxy/lib/mina-core-2.0.7.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/mina-integration-beans-2.0.7.jar
Normal file
BIN
bbb-videoproxy/lib/mina-integration-beans-2.0.7.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/mina-integration-jmx-2.0.7.jar
Normal file
BIN
bbb-videoproxy/lib/mina-integration-jmx-2.0.7.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/netty-3.2.7.Final.jar
Normal file
BIN
bbb-videoproxy/lib/netty-3.2.7.Final.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/red5-1.0r4643.jar
Normal file
BIN
bbb-videoproxy/lib/red5-1.0r4643.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/servlet-api-2.5.jar
Normal file
BIN
bbb-videoproxy/lib/servlet-api-2.5.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/slf4j-api-1.7.2.jar
Normal file
BIN
bbb-videoproxy/lib/slf4j-api-1.7.2.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/spring-aop-3.0.6.RELEASE.jar
Normal file
BIN
bbb-videoproxy/lib/spring-aop-3.0.6.RELEASE.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/spring-beans-3.1.1.RELEASE.jar
Normal file
BIN
bbb-videoproxy/lib/spring-beans-3.1.1.RELEASE.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/spring-context-3.1.1.RELEASE.jar
Normal file
BIN
bbb-videoproxy/lib/spring-context-3.1.1.RELEASE.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/spring-core-3.1.1.RELEASE.jar
Normal file
BIN
bbb-videoproxy/lib/spring-core-3.1.1.RELEASE.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/spring-web-3.1.1.RELEASE.jar
Normal file
BIN
bbb-videoproxy/lib/spring-web-3.1.1.RELEASE.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/testng-5.8.jar
Normal file
BIN
bbb-videoproxy/lib/testng-5.8.jar
Normal file
Binary file not shown.
BIN
bbb-videoproxy/lib/videoproxy-0.7.war
Normal file
BIN
bbb-videoproxy/lib/videoproxy-0.7.war
Normal file
Binary file not shown.
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||
*
|
||||
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along
|
||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.bigbluebutton.app.videoproxy;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
public class EventRecordingService {
|
||||
private static final String COLON = ":";
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
|
||||
public EventRecordingService(String host, int port) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void record(String meetingId, Map<String, String> event) {
|
||||
Jedis jedis = new Jedis(host, port);
|
||||
Long msgid = jedis.incr("global:nextRecordedMsgId");
|
||||
jedis.hmset("recording:" + meetingId + COLON + msgid, event);
|
||||
jedis.rpush("meeting:" + meetingId + COLON + "recordings", msgid.toString());
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package org.bigbluebutton.app.videoproxy;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.ChannelFactory;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelFutureListener;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.flazr.rtmp.client.ClientHandler;
|
||||
import com.flazr.rtmp.client.ClientOptions;
|
||||
|
||||
public abstract class RtmpConnection extends ClientHandler implements ChannelFutureListener {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RtmpConnection.class);
|
||||
|
||||
|
||||
|
||||
public RtmpConnection(ClientOptions options) {
|
||||
super(options);
|
||||
|
||||
}
|
||||
|
||||
private ClientBootstrap bootstrap = null;
|
||||
private ChannelFuture future = null;
|
||||
private ChannelFactory factory = null;
|
||||
|
||||
public boolean connect() {
|
||||
if (factory == null)
|
||||
factory = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
|
||||
bootstrap = new ClientBootstrap(factory);
|
||||
bootstrap.setPipelineFactory(pipelineFactory());
|
||||
future = bootstrap.connect(new InetSocketAddress(options.getHost(), options.getPort()));
|
||||
future.addListener(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
if (future != null) {
|
||||
if (future.getChannel().isConnected()) {
|
||||
log.debug("Channel is connected, disconnecting");
|
||||
future.getChannel().close(); //ClosedChannelException
|
||||
future.getChannel().getCloseFuture().awaitUninterruptibly();
|
||||
}
|
||||
future.removeListener(this);
|
||||
factory.releaseExternalResources();
|
||||
future = null; factory = null; bootstrap = null;
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected ChannelPipelineFactory pipelineFactory();
|
||||
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
if (future.isSuccess())
|
||||
onConnectedSuccessfully();
|
||||
else
|
||||
onConnectedUnsuccessfully();
|
||||
}
|
||||
|
||||
protected void onConnectedUnsuccessfully() {
|
||||
}
|
||||
|
||||
protected void onConnectedSuccessfully() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
||||
String exceptionMessage = e.getCause().getMessage();
|
||||
if (exceptionMessage != null && exceptionMessage.contains("ArrayIndexOutOfBoundsException") && exceptionMessage.contains("bad value / byte: 101 (hex: 65)")) {
|
||||
log.debug("Ignoring malformed metadata");
|
||||
return;
|
||||
} else {
|
||||
super.exceptionCaught(ctx, e);
|
||||
|
||||
//for (OnExceptionListener listener : context.getExceptionListeners())
|
||||
// listener.onException(e.getCause());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
/**
|
||||
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||
*
|
||||
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along
|
||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.bigbluebutton.app.videoproxy;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.red5.logging.Red5LoggerFactory;
|
||||
import org.red5.server.adapter.MultiThreadedApplicationAdapter;
|
||||
import org.red5.server.api.IConnection;
|
||||
import org.red5.server.api.Red5;
|
||||
import org.red5.server.api.scope.IScope;
|
||||
import org.red5.server.api.scope.IBasicScope;
|
||||
import org.red5.server.api.scope.IBroadcastScope;
|
||||
import org.red5.server.api.scope.ScopeType;
|
||||
import org.red5.server.api.stream.IBroadcastStream;
|
||||
import org.red5.server.api.stream.IServerStream;
|
||||
import org.red5.server.api.stream.IStreamListener;
|
||||
import org.red5.server.stream.ClientBroadcastStream;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class VideoApplication extends MultiThreadedApplicationAdapter {
|
||||
private static Logger log = Red5LoggerFactory.getLogger(VideoApplication.class, "video");
|
||||
|
||||
private IScope appScope;
|
||||
private IServerStream serverStream;
|
||||
|
||||
private boolean recordVideoStream = false;
|
||||
private EventRecordingService recordingService;
|
||||
private final Map<String, IStreamListener> streamListeners = new HashMap<String, IStreamListener>();
|
||||
|
||||
@Override
|
||||
public boolean appStart(IScope app) {
|
||||
super.appStart(app);
|
||||
log.info("oflaDemo appStart");
|
||||
System.out.println("oflaDemo appStart");
|
||||
appScope = app;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appConnect(IConnection conn, Object[] params) {
|
||||
log.info("oflaDemo appConnect");
|
||||
|
||||
return super.appConnect(conn, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appDisconnect(IConnection conn) {
|
||||
log.info("oflaDemo appDisconnect");
|
||||
if (appScope == conn.getScope() && serverStream != null) {
|
||||
serverStream.close();
|
||||
}
|
||||
super.appDisconnect(conn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamPublishStart(IBroadcastStream stream) {
|
||||
super.streamPublishStart(stream);
|
||||
}
|
||||
|
||||
|
||||
public IBroadcastScope getBroadcastScope(IScope scope, String name) {
|
||||
IBasicScope basicScope = scope.getBasicScope(ScopeType.BROADCAST, name);
|
||||
if (!(basicScope instanceof IBroadcastScope)) {
|
||||
return null;
|
||||
} else {
|
||||
return (IBroadcastScope) basicScope;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void streamBroadcastStart(IBroadcastStream stream) {
|
||||
IConnection conn = Red5.getConnectionLocal();
|
||||
super.streamBroadcastStart(stream);
|
||||
log.info("streamBroadcastStart " + stream.getPublishedName() + " " + System.currentTimeMillis() + " " + conn.getScope().getName());
|
||||
|
||||
|
||||
System.out.println("TESTE");
|
||||
System.out.println(conn.getScope().getName() + "-" + stream.getPublishedName());
|
||||
//VideoProxyReceiver(String host, String appPath, String conference, String streamName)
|
||||
/*if (recordVideoStream) {
|
||||
recordStream(stream);
|
||||
VideoStreamListener listener = new VideoStreamListener();
|
||||
listener.setEventRecordingService(recordingService);
|
||||
stream.addStreamListener(listener);
|
||||
streamListeners.put(conn.getScope().getName() + "-" + stream.getPublishedName(), listener);
|
||||
}
|
||||
*/
|
||||
|
||||
VideoProxyReceiver v = new VideoProxyReceiver("143.54.10.63", "videoproxy", "conferencia", stream.getPublishedName());
|
||||
v.start();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamBroadcastClose(IBroadcastStream stream) {
|
||||
IConnection conn = Red5.getConnectionLocal();
|
||||
super.streamBroadcastClose(stream);
|
||||
|
||||
if (recordVideoStream) {
|
||||
IStreamListener listener = streamListeners.remove(conn.getScope().getName() + "-" + stream.getPublishedName());
|
||||
if (listener != null) {
|
||||
stream.removeStreamListener(listener);
|
||||
}
|
||||
|
||||
long publishDuration = (System.currentTimeMillis() - stream.getCreationTime()) / 1000;
|
||||
log.info("streamBroadcastClose " + stream.getPublishedName() + " " + System.currentTimeMillis() + " " + conn.getScope().getName());
|
||||
Map<String, String> event = new HashMap<String, String>();
|
||||
event.put("module", "WEBCAM");
|
||||
event.put("timestamp", new Long(System.currentTimeMillis()).toString());
|
||||
event.put("meetingId", conn.getScope().getName());
|
||||
event.put("stream", stream.getPublishedName());
|
||||
event.put("duration", new Long(publishDuration).toString());
|
||||
event.put("eventName", "StopWebcamShareEvent");
|
||||
|
||||
recordingService.record(conn.getScope().getName(), event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A hook to record a stream. A file is written in webapps/video/streams/
|
||||
* @param stream
|
||||
*/
|
||||
private void recordStream(IBroadcastStream stream) {
|
||||
IConnection conn = Red5.getConnectionLocal();
|
||||
long now = System.currentTimeMillis();
|
||||
String recordingStreamName = stream.getPublishedName(); // + "-" + now; /** Comment out for now...forgot why I added this - ralam */
|
||||
|
||||
try {
|
||||
log.info("Recording stream " + recordingStreamName );
|
||||
ClientBroadcastStream cstream = (ClientBroadcastStream) this.getBroadcastStream(conn.getScope(), stream.getPublishedName());
|
||||
cstream.saveAs(recordingStreamName, false);
|
||||
} catch(Exception e) {
|
||||
log.error("ERROR while recording stream " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setRecordVideoStream(boolean recordVideoStream) {
|
||||
this.recordVideoStream = recordVideoStream;
|
||||
}
|
||||
|
||||
public void setEventRecordingService(EventRecordingService s) {
|
||||
recordingService = s;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* GT-Mconf: Multiconference system for interoperable web and mobile
|
||||
* http://www.inf.ufrgs.br/prav/gtmconf
|
||||
* PRAV Labs - UFRGS
|
||||
*
|
||||
* This file is part of Mconf-Mobile.
|
||||
*
|
||||
* Mconf-Mobile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Mconf-Mobile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Mconf-Mobile. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.bigbluebutton.app.videoproxy;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.flazr.rtmp.client.ClientOptions;
|
||||
import com.flazr.rtmp.message.Video;
|
||||
import com.flazr.util.Utils;
|
||||
|
||||
public class VideoProxyReceiver {
|
||||
|
||||
protected class VideoConnection extends VideoProxyReceiverConnection {
|
||||
|
||||
public VideoConnection(ClientOptions options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onVideo(Video video) {
|
||||
VideoProxyReceiver.this.onVideo(video);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(VideoProxyReceiver.class);
|
||||
|
||||
private String streamName;
|
||||
private VideoConnection videoConnection;
|
||||
|
||||
public VideoProxyReceiver(String host, String appPath, String conference, String streamName) {
|
||||
System.out.println("INIT");
|
||||
ClientOptions opt = new ClientOptions();
|
||||
opt.setClientVersionToUse(Utils.fromHex("00000000"));
|
||||
opt.setHost(host);
|
||||
opt.setAppName(appPath + "/" + conference);
|
||||
|
||||
this.streamName = streamName;
|
||||
|
||||
opt.setWriterToSave(null);
|
||||
opt.setStreamName(streamName);
|
||||
|
||||
videoConnection = new VideoConnection(opt);
|
||||
System.out.println("COMP");
|
||||
}
|
||||
|
||||
protected void onVideo(Video video) {
|
||||
//Retransmit video package
|
||||
//Received Video
|
||||
System.out.println("Received Video data " + video.getHeader().getTime());
|
||||
log.debug("received video package: {}", video.getHeader().getTime());
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (videoConnection != null)
|
||||
videoConnection.connect();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (videoConnection != null)
|
||||
videoConnection.disconnect();
|
||||
}
|
||||
|
||||
|
||||
public String getStreamName() {
|
||||
return streamName;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* GT-Mconf: Multiconference system for interoperable web and mobile
|
||||
* http://www.inf.ufrgs.br/prav/gtmconf
|
||||
* PRAV Labs - UFRGS
|
||||
*
|
||||
* This file is part of Mconf-Mobile.
|
||||
*
|
||||
* Mconf-Mobile is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Mconf-Mobile is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Mconf-Mobile. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.bigbluebutton.app.videoproxy;
|
||||
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelPipeline;
|
||||
import org.jboss.netty.channel.ChannelPipelineFactory;
|
||||
import org.jboss.netty.channel.ChannelStateEvent;
|
||||
import org.jboss.netty.channel.Channels;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.flazr.rtmp.RtmpDecoder;
|
||||
import com.flazr.rtmp.RtmpEncoder;
|
||||
import com.flazr.rtmp.RtmpMessage;
|
||||
import com.flazr.rtmp.client.ClientHandshakeHandler;
|
||||
import com.flazr.rtmp.client.ClientOptions;
|
||||
import com.flazr.rtmp.message.Command;
|
||||
import com.flazr.rtmp.message.MessageType;
|
||||
import com.flazr.rtmp.message.Video;
|
||||
|
||||
public abstract class VideoProxyReceiverConnection extends RtmpConnection {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final Logger log = LoggerFactory.getLogger(VideoProxyReceiverConnection.class);
|
||||
|
||||
public VideoProxyReceiverConnection(ClientOptions options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChannelPipelineFactory pipelineFactory() {
|
||||
return new ChannelPipelineFactory() {
|
||||
@Override
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
final ChannelPipeline pipeline = Channels.pipeline();
|
||||
pipeline.addLast("handshaker", new ClientHandshakeHandler(options));
|
||||
pipeline.addLast("decoder", new RtmpDecoder());
|
||||
pipeline.addLast("encoder", new RtmpEncoder());
|
||||
pipeline.addLast("handler", VideoProxyReceiverConnection.this);
|
||||
return pipeline;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||
options.setArgs((Object[]) null);
|
||||
writeCommandExpectingResult(e.getChannel(), Command.connect(options));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMultimedia(Channel channel, RtmpMessage message) {
|
||||
super.onMultimedia(channel, message);
|
||||
if (message.getHeader().getMessageType() == MessageType.VIDEO) {
|
||||
onVideo((Video) message);
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void onVideo(Video video);
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||
*
|
||||
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along
|
||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.bigbluebutton.app.videoproxy;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.apache.mina.core.buffer.IoBuffer;
|
||||
import org.red5.server.api.IConnection;
|
||||
import org.red5.server.api.Red5;
|
||||
import org.red5.server.api.stream.IBroadcastStream;
|
||||
import org.red5.server.api.stream.IStreamListener;
|
||||
import org.red5.server.api.stream.IStreamPacket;
|
||||
import org.red5.server.net.rtmp.event.VideoData;
|
||||
|
||||
/**
|
||||
* Class to listen for the first video packet of the webcam.
|
||||
* We need to listen for the first packet and send a startWebcamEvent.
|
||||
* The reason is that when starting the webcam, sometimes Flash Player
|
||||
* needs to prompt the user for permission to access the webcam. However,
|
||||
* while waiting for the user to click OK to the prompt, Red5 has already
|
||||
* called the startBroadcast method which we take as the start of the recording.
|
||||
* When the user finally clicks OK, the packets then start to flow through.
|
||||
* This introduces a delay of when we assume the start of the recording and
|
||||
* the webcam actually publishes video packets. When we do the ingest and
|
||||
* processing of the video and multiplex the audio, the video and audio will
|
||||
* be un-synched by at least this amount of delay.
|
||||
* @author Richard Alam
|
||||
*
|
||||
*/
|
||||
public class VideoStreamListener implements IStreamListener {
|
||||
private EventRecordingService recordingService;
|
||||
private volatile boolean firstPacketReceived = false;
|
||||
|
||||
@Override
|
||||
public void packetReceived(IBroadcastStream stream, IStreamPacket packet) {
|
||||
IoBuffer buf = packet.getData();
|
||||
if (buf != null)
|
||||
buf.rewind();
|
||||
|
||||
if (buf == null || buf.remaining() == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet instanceof VideoData) {
|
||||
if (! firstPacketReceived) {
|
||||
firstPacketReceived = true;
|
||||
IConnection conn = Red5.getConnectionLocal();
|
||||
Map<String, String> event = new HashMap<String, String>();
|
||||
event.put("module", "WEBCAM");
|
||||
event.put("timestamp", new Long(System.currentTimeMillis()).toString());
|
||||
event.put("meetingId", conn.getScope().getName());
|
||||
event.put("stream", stream.getPublishedName());
|
||||
event.put("eventName", "StartWebcamShareEvent");
|
||||
|
||||
recordingService.record(conn.getScope().getName(), event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setEventRecordingService(EventRecordingService s) {
|
||||
recordingService = s;
|
||||
}
|
||||
|
||||
}
|
20
bbb-videoproxy/src/main/resources/logback-video.xml
Executable file
20
bbb-videoproxy/src/main/resources/logback-video.xml
Executable file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="VIDEOPROXY" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<File>log/videoproxy.log</File>
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>log/videoproxy.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
<!-- keep 5 days worth of history -->
|
||||
<MaxHistory>5</MaxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<Pattern>%date [%thread] %-5level %logger{35} - %msg%n</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
<root>
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="VIDEOPROXY" />
|
||||
</root>
|
||||
</configuration>
|
2
bbb-videoproxy/src/main/webapp/WEB-INF/bigbluebutton-video.properties
Executable file
2
bbb-videoproxy/src/main/webapp/WEB-INF/bigbluebutton-video.properties
Executable file
@ -0,0 +1,2 @@
|
||||
redis.host=127.0.0.1
|
||||
redis.port=6379
|
@ -0,0 +1,2 @@
|
||||
webapp.contextPath=/videoproxy
|
||||
webapp.virtualHosts=*, localhost, localhost:8088, 127.0.0.1:8088
|
57
bbb-videoproxy/src/main/webapp/WEB-INF/red5-web.xml
Executable file
57
bbb-videoproxy/src/main/webapp/WEB-INF/red5-web.xml
Executable file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||
|
||||
Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">
|
||||
|
||||
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
|
||||
<property name="locations">
|
||||
<list>
|
||||
<value>/WEB-INF/red5-web.properties</value>
|
||||
<value>/WEB-INF/bigbluebutton-video.properties</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="web.context" class="org.red5.server.Context"
|
||||
autowire="byType" />
|
||||
|
||||
<bean id="web.scope" class="org.red5.server.scope.WebScope" init-method="register">
|
||||
<property name="server" ref="red5.server" />
|
||||
<property name="parent" ref="global.scope" />
|
||||
<property name="context" ref="web.context" />
|
||||
<property name="handler" ref="web.handler" />
|
||||
<property name="contextPath" value="${webapp.contextPath}" />
|
||||
<property name="virtualHosts" value="${webapp.virtualHosts}" />
|
||||
</bean>
|
||||
|
||||
<bean id="web.handler" class="org.bigbluebutton.app.videoproxy.VideoApplication">
|
||||
<property name="recordVideoStream" value="true"/>
|
||||
<property name="eventRecordingService" ref="redisRecorder"/>
|
||||
</bean>
|
||||
|
||||
<bean id="redisRecorder" class="org.bigbluebutton.app.videoproxy.EventRecordingService">
|
||||
<constructor-arg index="0" value="${redis.host}"/>
|
||||
<constructor-arg index="1" value="${redis.port}"/>
|
||||
</bean>
|
||||
</beans>
|
56
bbb-videoproxy/src/main/webapp/WEB-INF/web.xml
Executable file
56
bbb-videoproxy/src/main/webapp/WEB-INF/web.xml
Executable file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!--
|
||||
|
||||
BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||
|
||||
Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-->
|
||||
<web-app
|
||||
xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
|
||||
version="2.4">
|
||||
<display-name>BigBlueButton Video Proxy Application</display-name>
|
||||
|
||||
<context-param>
|
||||
<param-name>webAppRootKey</param-name>
|
||||
<param-value>/videoproxy</param-value>
|
||||
</context-param>
|
||||
|
||||
|
||||
<listener>
|
||||
<listener-class>org.red5.logging.ContextLoggingListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<filter>
|
||||
<filter-name>LoggerContextFilter</filter-name>
|
||||
<filter-class>org.red5.logging.LoggerContextFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>LoggerContextFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Forbidden</web-resource-name>
|
||||
<url-pattern>/streams/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint/>
|
||||
</security-constraint>
|
||||
|
||||
</web-app>
|
1
bbb-videoproxy/src/main/webapp/streams/README
Executable file
1
bbb-videoproxy/src/main/webapp/streams/README
Executable file
@ -0,0 +1 @@
|
||||
Do not delete the streams directory. This is where the video recordings will be saved.
|
@ -46,7 +46,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
public function get uri():String {
|
||||
LogUtil.debug("URL eh: " + _attributes.uri + "/" + _attributes.room);
|
||||
return _attributes.uri + "/" + _attributes.room;
|
||||
|
||||
//return _attributes.uri + "/" + _attributes.room;
|
||||
return "rtmp://143.54.10.63/videoproxy" + "/" + _attributes.room;
|
||||
}
|
||||
|
||||
public function get username():String {
|
||||
|
@ -69,7 +69,9 @@ package org.bigbluebutton.modules.videoconf.business
|
||||
}
|
||||
|
||||
public function connect():void {
|
||||
nc.connect(_url);
|
||||
LogUtil.debug("OLD: " + _url);
|
||||
_url = "rtmp://143.54.10.63/videoproxy/conferencia";
|
||||
nc.connect(_url);
|
||||
}
|
||||
|
||||
private function onAsyncError(event:AsyncErrorEvent):void{
|
||||
|
@ -215,6 +215,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
LogUtil.debug("Playing MY_STRING 2");
|
||||
this.streamName = "MY_STRING";
|
||||
|
||||
ns.play("MY_STRING");
|
||||
|
||||
this.width = _video.width + paddingHorizontal;
|
||||
this.height = _video.height + paddingVertical;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user