From: <fg...@us...> - 2010-05-04 21:19:45
|
Revision: 2350 http://openutils.svn.sourceforge.net/openutils/?rev=2350&view=rev Author: fgiust Date: 2010-05-04 21:19:37 +0000 (Tue, 04 May 2010) Log Message: ----------- MEDIA-136 RTMP support: handle flv metadata fetching Modified Paths: -------------- trunk/openutils-mgnlmedia/pom.xml trunk/openutils-mgnlmedia/src/main/assembly/assembly-bundle.xml trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/types/impl/ExternalVideoTypeHandler.java trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/utils/FLVMedataUtils.java Added Paths: ----------- trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/utils/RtmpMedatadaFetcher.java Modified: trunk/openutils-mgnlmedia/pom.xml =================================================================== --- trunk/openutils-mgnlmedia/pom.xml 2010-05-04 20:44:52 UTC (rev 2349) +++ trunk/openutils-mgnlmedia/pom.xml 2010-05-04 21:19:37 UTC (rev 2350) @@ -1,4 +1,5 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <parent> <groupId>net.sourceforge.openutils</groupId> <artifactId>openutils-parent</artifactId> @@ -141,6 +142,25 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>com.flazr</groupId> + <artifactId>flazr</artifactId> + <version>0.7-snv20100505</version> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>jcl104-over-slf4j</artifactId> + </exclusion> + <exclusion> + <groupId>commons-cli</groupId> + <artifactId>commons-cli</artifactId> + </exclusion> + <exclusion> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>1.0.0</version> @@ -167,9 +187,9 @@ </dependencies> <repositories> <repository> - <id>repository.magnolia-cms.com</id> - <name>magnolia repository</name> - <url>http://repository.magnolia-cms.com/m2</url> + <id>repository.openmindonline.it</id> + <name>openmindonline repository</name> + <url>http://repository.openmindonline.it</url> <releases> <enabled>true</enabled> </releases> @@ -179,6 +199,6 @@ </repository> </repositories> <properties> - <magnolia.version>4.3</magnolia.version> + <magnolia.version>4.3.1</magnolia.version> </properties> </project> \ No newline at end of file Modified: trunk/openutils-mgnlmedia/src/main/assembly/assembly-bundle.xml =================================================================== --- trunk/openutils-mgnlmedia/src/main/assembly/assembly-bundle.xml 2010-05-04 20:44:52 UTC (rev 2349) +++ trunk/openutils-mgnlmedia/src/main/assembly/assembly-bundle.xml 2010-05-04 21:19:37 UTC (rev 2350) @@ -31,6 +31,8 @@ <include>net.sourceforge.openutils:*</include> <include>com.google.collections:*</include> <include>org.apache.pdfbox:*</include> + <include>com.flazr:flazr:*</include> + <include>org.jboss.netty:netty:*</include> </includes> </dependencySet> </dependencySets> Modified: trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/types/impl/ExternalVideoTypeHandler.java =================================================================== --- trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/types/impl/ExternalVideoTypeHandler.java 2010-05-04 20:44:52 UTC (rev 2349) +++ trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/types/impl/ExternalVideoTypeHandler.java 2010-05-04 21:19:37 UTC (rev 2350) @@ -42,6 +42,7 @@ import net.sourceforge.openutils.mgnlmedia.media.types.externals.ExternalVideoSupport; import net.sourceforge.openutils.mgnlmedia.media.utils.FLVMedataUtils; +import net.sourceforge.openutils.mgnlmedia.media.utils.RtmpMedatadaFetcher; import net.sourceforge.openutils.mgnlmedia.media.utils.FLVMedataUtils.FLVMetaData; import org.apache.commons.io.IOUtils; @@ -238,8 +239,16 @@ try { - URL url = new URL(downloadUrl); - return FLVMedataUtils.parseFLVfromUrl(url); + if (StringUtils.startsWith(downloadUrl, "http")) + { + URL url = new URL(downloadUrl); + return FLVMedataUtils.parseFLVfromUrl(url); + } + else if (StringUtils.startsWith(downloadUrl, "rtmp")) + { + return RtmpMedatadaFetcher.fetchMetadata(downloadUrl, 10000); + } + } catch (Throwable e) { @@ -249,8 +258,8 @@ + e.getMessage() + ") while parsing URL " + downloadUrl); - return null; } + return null; } /** Modified: trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/utils/FLVMedataUtils.java =================================================================== --- trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/utils/FLVMedataUtils.java 2010-05-04 20:44:52 UTC (rev 2349) +++ trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/utils/FLVMedataUtils.java 2010-05-04 21:19:37 UTC (rev 2350) @@ -21,7 +21,6 @@ import java.io.IOException; import java.io.InputStream; -import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.nio.ByteBuffer; @@ -198,17 +197,7 @@ // Reading the data from the input stream fis.read(bytes); - // Fetching the properties. If the output shows -1 or null then consider that the FLV doesn't have that - // info on metadata - meta.setDuration(getLong(bytes, "duration")); - meta.setWidth(getLong(bytes, "width")); - meta.setHeight(getLong(bytes, "height")); - meta.setAudioDataRate(getDouble(bytes, "audiodatarate")); - meta.setVideoDataRate(getDouble(bytes, "videodatarate")); - meta.setFileSize(getLong(bytes, "filesize")); - meta.setCreatedDate(getString(bytes, "creationdate")); - meta.setMimeType(getString(bytes, "mimetype")); - meta.setFrameRate(getDouble(bytes, "framerate")); + meta = getMetaData(bytes); } finally @@ -219,6 +208,30 @@ return meta; } + /** + * @param meta + * @param bytes + */ + protected static FLVMetaData getMetaData(byte[] bytes) + { + + FLVMetaData meta = new FLVMetaData(); + + // Fetching the properties. If the output shows -1 or null then consider that the FLV doesn't have that + // info on metadata + meta.setDuration(getLong(bytes, "duration")); + meta.setWidth(getLong(bytes, "width")); + meta.setHeight(getLong(bytes, "height")); + meta.setAudioDataRate(getDouble(bytes, "audiodatarate")); + meta.setVideoDataRate(getDouble(bytes, "videodatarate")); + meta.setFileSize(getLong(bytes, "filesize")); + meta.setCreatedDate(getString(bytes, "creationdate")); + meta.setMimeType(getString(bytes, "mimetype")); + meta.setFrameRate(getDouble(bytes, "framerate")); + + return meta; + } + private static double getDouble(byte[] bytes, String property) { // Checking whether the property exists on the metadata Added: trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/utils/RtmpMedatadaFetcher.java =================================================================== --- trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/utils/RtmpMedatadaFetcher.java (rev 0) +++ trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/utils/RtmpMedatadaFetcher.java 2010-05-04 21:19:37 UTC (rev 2350) @@ -0,0 +1,203 @@ +/** + * + * Magnolia SimpleMedia Module (http://www.openmindlab.com/lab/products/media.html) + * Copyright (C)2008 - 2010, Openmind S.r.l. http://www.openmindonline.it + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package net.sourceforge.openutils.mgnlmedia.media.utils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +import net.sourceforge.openutils.mgnlmedia.media.utils.FLVMedataUtils.FLVMetaData; + +import org.apache.commons.lang.StringUtils; +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.flazr.io.flv.FlvAtom; +import com.flazr.rtmp.RtmpHeader; +import com.flazr.rtmp.RtmpMessage; +import com.flazr.rtmp.RtmpWriter; +import com.flazr.rtmp.client.ClientOptions; +import com.flazr.rtmp.client.ClientPipelineFactory; + + +/** + * <p>Utility class to fetch flv headers from a rtmp URL using flazr (http://flazr.com)</p> + * @author fgiust + * @version $Id$ + */ +public final class RtmpMedatadaFetcher +{ + + private RtmpMedatadaFetcher() + { + // don't instantiate + } + + /** + * Fetch flv metadata from a rtmp URL + * @param url URL + * @param timeoutInMs timeout for fetching metadata (milliseconds) + * @return parsed FLVMetadata + * @throws IOException + */ + public static FLVMetaData fetchMetadata(String url, long timeoutInMs) throws IOException + { + + String validUrl = StringUtils.substringBeforeLast(url, ".flv"); + + // sample url: "rtmp://edge01.fms.dutchview.nl/botr/bunny" + ClientOptions options = new ClientOptions(validUrl, null); + + options.setLoad(1); + options.getSwfHash(); + options.setLength(1); + MetadataWriter writer = new MetadataWriter(); + options.setWriterToSave(writer); + + final ClientBootstrap bootstrap = getBootstrap(Executors.newCachedThreadPool(), options); + final ChannelFuture future = bootstrap.connect(new InetSocketAddress(options.getHost(), options.getPort())); + + for (int j = 0; j < (timeoutInMs / 10); j++) + { + if (writer.getByteArray().size() >= 400) + { + break; + } + future.getChannel().getCloseFuture().awaitUninterruptibly(10); + } + + bootstrap.getFactory().releaseExternalResources(); + + return FLVMedataUtils.getMetaData(writer.getByteArray().toByteArray()); + } + + private static ClientBootstrap getBootstrap(final Executor executor, final ClientOptions options) + { + final ChannelFactory factory = new NioClientSocketChannelFactory(executor, executor); + final ClientBootstrap bootstrap = new ClientBootstrap(factory); + bootstrap.setPipelineFactory(new ClientPipelineFactory(options)); + bootstrap.setOption("tcpNoDelay", true); + bootstrap.setOption("keepAlive", true); + return bootstrap; + } + + static class MetadataWriter implements RtmpWriter + { + + /** + * Logger. + */ + private Logger log = LoggerFactory.getLogger(RtmpMedatadaFetcher.MetadataWriter.class); + + private final ByteArrayOutputStream bos; + + private final int[] channelTimes = new int[RtmpHeader.MAX_CHANNEL_ID]; + + private int primaryChannel = -1; + + private final int seekTime; + + public MetadataWriter() + { + bos = new ByteArrayOutputStream(); + + this.seekTime = 0; + + try + { + bos.write(FlvAtom.flvHeader().toByteBuffer().array()); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + /** + * {@inheritDoc} + */ + public void close() + { + // nothing to do + } + + /** + * {@inheritDoc} + */ + public void write(final RtmpMessage message) + { + final RtmpHeader header = message.getHeader(); + if (header.isAggregate()) + { + final ChannelBuffer in = message.encode(); + while (in.readable()) + { + final FlvAtom flvAtom = new FlvAtom(in); + final int absoluteTime = flvAtom.getHeader().getTime(); + channelTimes[primaryChannel] = absoluteTime; + write(flvAtom); + } + } + else + { + final int channelId = header.getChannelId(); + channelTimes[channelId] = seekTime + header.getTime(); + if (primaryChannel == -1 && (header.isAudio() || header.isVideo())) + { + log.info("first media packet for channel: {}", header); + primaryChannel = channelId; + } + if (header.getSize() <= 2) + { + return; + } + write(new FlvAtom(header.getMessageType(), channelTimes[channelId], message.encode())); + } + } + + private void write(final FlvAtom flvAtom) + { + try + { + bos.write(flvAtom.write().toByteBuffer().array()); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + /** + * Returns the ByteArrayOutputStream. + * @return the ByteArrayOutputStream + */ + public ByteArrayOutputStream getByteArray() + { + return bos; + } + + } +} Property changes on: trunk/openutils-mgnlmedia/src/main/java/net/sourceforge/openutils/mgnlmedia/media/utils/RtmpMedatadaFetcher.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |