public class JmsContainer extends DefaultMessageListenerContainer { private static final Logger logger = Logger.getLogger(JmsContainer.class); public void start(){ startAdvisoryListener(); super.start(); } private void startAdvisoryListener(){ javax.jms.Connection connection; try { connection = getConnectionFactory().createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); connection.start(); Destination topic = session.createTopic("ActiveMQ.Advisory..>"); MessageConsumer consumerAdvisory = session.createConsumer(topic); consumerAdvisory.setMessageListener(new MessageListener() { public void onMessage(Message message) { if (message instanceof ActiveMQMessage) { ActiveMQMessage activeMessage = (ActiveMQMessage) message; Object command = activeMessage.getDataStructure(); if (command instanceof ConsumerInfo) { logger.info("A consumer subscribed to a topic or queue: " + command); } else if (command instanceof RemoveInfo) { RemoveInfo removeInfo = (RemoveInfo) command; if (removeInfo.isConsumerRemove()) { logger.info("A consumer unsubscribed from a topic or queue"); } else { logger.info("RemoveInfo, a connection was closed: " + command); } } else if (command instanceof ConnectionInfo) { logger.info("ConnectionInfo, a new connection was made: " + command); } else { logger.info("Unknown command: " + command); } } } }); } catch (JMSException e) { e.printStackTrace(); } } }
Friday, March 25, 2011
How to listen JMS disconnection?
I refere this.
Labels:
JMS
Wednesday, February 16, 2011
Wicket push reload support
When I look the cometd's instruction page here, it seems the the based source code do not support reload. As shown in the example, it requires a client side javascript code. But it was not written anywhere, as far as I saw.
I start supporting reload extension on my custom wicketstuff-push (see the post). Let's see the code.
I add a javascript file. This code is written based on the reload example for jQuery (here).
Be care that this works on not only browser reloads, but also loading the same page with different parameters. It means, subscribing to the different channel also happens without handshake.
I start supporting reload extension on my custom wicketstuff-push (see the post). Let's see the code.
public abstract class CometdAbstractBehavior extends AbstractDefaultAjaxBehavior { private static final long serialVersionUID = 1L; // FIXME: put this in application scope, we may have several webapp using // CometdBehavior in the same web container! private final static String cometdServletPath = getCometdServletPath(); private static final ResourceReference COMETD = new CompressedResourceReference(CometdAbstractBehavior.class, "org/cometd.js"); private static final ResourceReference JQ_JSON2 = new CompressedResourceReference(CometdAbstractBehavior.class, "jquery/json2.js"); private static final ResourceReference JQ_COMETD = new CompressedResourceReference(CometdAbstractBehavior.class, "jquery/jquery.cometd.js"); private static final ResourceReference COMETD_RELOAD = new CompressedResourceReference(CometdAbstractBehavior.class, "org/cometd/ReloadExtension.js"); private static final ResourceReference JQ_COOKIE = new CompressedResourceReference(CometdAbstractBehavior.class, "jquery/jquery.cookie.js"); private static final ResourceReference JQ_COMETD_RELOAD = new CompressedResourceReference(CometdAbstractBehavior.class, "jquery/jquery.cometd-reload.js"); @Override public void renderHead(final IHeaderResponse response) { super.renderHead(response); if (channelId == null) { throw new IllegalArgumentException("ChannelId in a CometdBehavior can not be null"); } response.renderJavascriptReference(COMETD); response.renderJavascriptReference(JQ_JSON2); response.renderJavascriptReference(JQ_COMETD); response.renderJavascriptReference(COMETD_RELOAD); response.renderJavascriptReference(JQ_COOKIE); response.renderJavascriptReference(JQ_COMETD_RELOAD); response.renderJavascript(getInitCometdScript(), "initCometd"); final String cometdInterceptorScript = getCometdInterceptorScript(); if (cometdInterceptorScript != null) { response.renderJavascript(cometdInterceptorScript, "Interceptor" + getBehaviorMarkupId()); } response.renderJavascript(getSubscriberScript(), "Subscribe" + getBehaviorMarkupId()); } protected final CharSequence getInitCometdScript() { return new PackagedTextTemplate(CometdBehavior.class, "CometdReloadInit.js").getString() + getConfigureCometdScript() + getHandshakeCometdScript(); }
I add a javascript file. This code is written based on the reload example for jQuery (here).
/* handshake listener to report client IDs */ $.cometd.addListener("/meta/handshake", function(message) { if (message.successful) { $('#previous').html(org.cometd.COOKIE.get('demoLastCometdID')); $('#current').html(message.clientId); org.cometd.COOKIE.set('demoLastCometdID', message.clientId, { 'max-age': 300, path : '/', expires: new Date(new Date().getTime() + 300 * 1000) }); } else { $('#previous').html('Handshake Failed'); $('#current').html('Handshake Failed'); } }); /* Setup reload extension */ $(window).unload(function() { $.cometd.reload(); });
Be care that this works on not only browser reloads, but also loading the same page with different parameters. It means, subscribing to the different channel also happens without handshake.
Saturday, February 12, 2011
Wicket push
Wicketstuff push has dramatically changed at 1.4.13. But the API changes so much at that version, and I cannot make it work. Since the 1.4.12 uses very OLD dojo libraries, I want to migrate to the new version.
While looking the release documents of Cometd 2.1.0, I find that it supports jQuery bindings and Dojo bindings. So, I try to change the bindings to jQuery based on 1.4.12.
The files I have changed are two, CometdAbstractBehavior.java, CometdBehavior.java. And import javascripts from cometd-javascript-jquery-2.1.0.war.
Yes, it works. Thanks for chrome's developer tool. It helps me lot! And I also refer this.
While looking the release documents of Cometd 2.1.0, I find that it supports jQuery bindings and Dojo bindings. So, I try to change the bindings to jQuery based on 1.4.12.
The files I have changed are two, CometdAbstractBehavior.java, CometdBehavior.java. And import javascripts from cometd-javascript-jquery-2.1.0.war.
public abstract class CometdAbstractBehavior extends AbstractDefaultAjaxBehavior { private static final long serialVersionUID = 1L; // FIXME: put this in application scope, we may have several webapp using // CometdBehavior in the same web container! private final static String cometdServletPath = getCometdServletPath(); private static final ResourceReference COMETD = new CompressedResourceReference(CometdAbstractBehavior.class, "org/cometd.js"); private static final ResourceReference JQ_JSON2 = new CompressedResourceReference(CometdAbstractBehavior.class, "jquery/json2.js"); private static final ResourceReference JQ_COMETD = new CompressedResourceReference(CometdAbstractBehavior.class, "jquery/jquery.cometd.js"); @Override public void renderHead(final IHeaderResponse response) { super.renderHead(response); if (channelId == null) { throw new IllegalArgumentException("ChannelId in a CometdBehavior can not be null"); } response.renderJavascriptReference(COMETD); response.renderJavascriptReference(JQ_JSON2); response.renderJavascriptReference(JQ_COMETD); response.renderJavascript(getInitCometdScript(), "initCometd"); final String cometdInterceptorScript = getCometdInterceptorScript(); if (cometdInterceptorScript != null) { response.renderJavascript(cometdInterceptorScript, "Interceptor" + getBehaviorMarkupId()); } response.renderJavascript(getSubscriberScript(), "Subscribe" + getBehaviorMarkupId()); } protected final CharSequence getInitCometdScript() { return getConfigureCometdScript() + getHandshakeCometdScript(); } protected final String getConfigureCometdScript() { return "$.cometd.configure('" + cometdServletPath + "')\n"; } protected String getHandshakeCometdScript() { return "$.cometd.handshake()\n"; } public final CharSequence getSubscriberScript() { return "$.cometd.subscribe('/" + getChannelId() + "', " + getPartialSubscriber() + ");\n"; }
public class CometdBehavior extends CometdAbstractBehavior { @Override public final String getCometdInterceptorScript() { final Mapmap = new HashMap (); map.put("behaviorMarkupId", getBehaviorMarkupId()); map.put("url", getCallbackUrl().toString()); return new PackagedTextTemplate(CometdBehavior.class, "CometdDefaultBehaviorTemplate.js").asString(map); } @Override public final CharSequence getPartialSubscriber() { return "onEventFor" + getBehaviorMarkupId(); }
Yes, it works. Thanks for chrome's developer tool. It helps me lot! And I also refer this.
Friday, February 4, 2011
Wicket: NavigatorLabel for GridView
It seems that the NavigatorLabel do not support GridView. So I make it based on the Original NavigatorLabel. It's very simple.
/** * Label that provides Showing x to y of z message given for a DataTable. The message can be * overridden using the <code>NavigatorLabel</code> property key, the default message is used is of * the format <code>Showing ${from} to ${to} of ${of}</code>. The message can also be configured * pragmatically by setting it as the model object of the label. * * @author Igor Vaynberg (ivaynberg) * */ public class GridNavigatorLabel extends Label { private static final long serialVersionUID = 1L; // TODO Factor this interface out and let dataview/datatable implement it private static interface PageableComponent extends IClusterable { /** * @return total number of rows across all pages */ int getRowCount(); /** * @return current page */ int getCurrentPage(); /** * @return rows per page */ int getRowsPerPage(); int getColumnsPerRow(); } /** * @param id * component id * @param table * table */ public GridNavigatorLabel(final String id, final GridView<?> table) { this(id, new PageableComponent() { /** * */ private static final long serialVersionUID = 1L; public int getCurrentPage() { return table.getCurrentPage(); } public int getRowCount() { return table.getRowCount(); } public int getRowsPerPage() { return table.getRows(); } public int getColumnsPerRow() { return table.getColumns(); } }); } private GridNavigatorLabel(final String id, final PageableComponent table) { super(id); setDefaultModel(new StringResourceModel("NavigatorLabel", this, new Model<LabelModelObject>(new LabelModelObject(table)), "Showing ${from} to ${to} of ${of}")); } private class LabelModelObject implements IClusterable { private static final long serialVersionUID = 1L; private final PageableComponent table; /** * Construct. * * @param table */ public LabelModelObject(PageableComponent table) { this.table = table; } /** * @return "z" in "Showing x to y of z" */ public int getOf() { return table.getRowCount(); } /** * @return "x" in "Showing x to y of z" */ public int getFrom() { if (getOf() == 0) { return 0; } return (table.getCurrentPage() * table.getRowsPerPage() * table.getColumnsPerRow()) + 1; } /** * @return "y" in "Showing x to y of z" */ public int getTo() { if (getOf() == 0) { return 0; } return Math.min(getOf(), getFrom() + table.getRowsPerPage()* table.getColumnsPerRow() - 1); } } }
Labels:
Wicket
Tuesday, February 1, 2011
Xuggler: resizing video using MediaTool API
There is a full source code for resizing video with MediaTool API. Look this. Great, thanks!
I added two lines.
The line 3 is what I mentioned at the previous post. The line 4 is a little bit tricky. I'm not sure why it works, but without the line 4, I got following errors.
I added two lines.
// resize IMediaReader reader = ToolFactory.makeReader(baseURL+this.streamName); reader.open(); reader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR); IMediaTool videoResizeTool = new VideoResizeTool(80,60); IMediaWriter writer = ToolFactory.makeWriter(baseURL+this.transcodedStreamName, reader); SetVideoSizeListener setVideoSizeListener = new SetVideoSizeListener(80, 60); // pipeline reader -> VideoResizeTool -> writer -> setVideoSize reader.addListener(videoResizeTool); videoResizeTool.addListener(writer); writer.addListener(setVideoSizeListener); while (reader.readPacket() == null){ do {} while(false); }
The line 3 is what I mentioned at the previous post. The line 4 is a little bit tricky. I'm not sure why it works, but without the line 4, I got following errors.
13:15:22.483 [Thread-76] WARN com.xuggle.xuggler - Got error: picture is not of the same width as this Coder (../../../../../../../csrc/com/xuggle/xuggler/StreamCoder.cpp:1251) Exception in thread "Thread-76" java.lang.RuntimeException: failed to encode video at com.xuggle.mediatool.MediaWriter.encodeVideo(MediaWriter.java:771) at com.xuggle.mediatool.MediaWriter.encodeVideo(MediaWriter.java:790) at com.xuggle.mediatool.MediaWriter.onVideoPicture(MediaWriter.java:1441) at com.xuggle.mediatool.AMediaToolMixin.onVideoPicture(AMediaToolMixin.java:166) at com.xuggle.mediatool.MediaToolAdapter.onVideoPicture(MediaToolAdapter.java:169) at com.mycompany.xuggler.VideoResizeTool.onVideoPicture(VideoResizeTool.java:35) at com.xuggle.mediatool.AMediaToolMixin.onVideoPicture(AMediaToolMixin.java:166) at com.xuggle.mediatool.MediaReader.dispatchVideoPicture(MediaReader.java:610) at com.xuggle.mediatool.MediaReader.decodeVideo(MediaReader.java:519) at com.xuggle.mediatool.MediaReader.readPacket(MediaReader.java:475) at com.mycompany.xuggler.MediaProcessingThread.startMediaProcessing(MediaProcessingThread.java:96) at com.mycompany.xuggler.MediaProcessingThread.run(MediaProcessingThread.java:30)Is it because of the difference of versions? I'm using the latest revision 1065 not release 3.4.
Labels:
Xuggler
Xuggler: Using MediaTool API
I see the tutorial. And going to test MediaTool API for transcoding. I follow the section "How To Transcode Media From One Format To Another".
Greate very simple. Let's run....
Hm... It fails.... O.K. look into the source code.
IMediaReader reader = ToolFactory.makeReader(baseURL+this.streamName); IMediaWriter writer = ToolFactory.makeWriter(baseURL+this.transcodedStreamName, reader); reader.addListener(writer); while (reader.readPacket() == null){ do {} while(false); }
Greate very simple. Let's run....
11:41:29.983 [Thread-70] ERROR com.xuggle.xuggler - Could not find output format (../../../../../../../csrc/com/xuggle/xuggler/Container.cpp:338) Exception in thread "Thread-70" java.lang.IllegalArgumentException: could not open: rtmp://127.0.0.1/live/myStream at com.xuggle.mediatool.MediaWriter.open(MediaWriter.java:1289) at com.xuggle.mediatool.MediaWriter.getStream(MediaWriter.java:998) at com.xuggle.mediatool.MediaWriter.encodeVideo(MediaWriter.java:749) at com.xuggle.mediatool.MediaWriter.encodeVideo(MediaWriter.java:790) at com.xuggle.mediatool.MediaWriter.onVideoPicture(MediaWriter.java:1441) at com.xuggle.mediatool.AMediaToolMixin.onVideoPicture(AMediaToolMixin.java:166) at com.xuggle.mediatool.MediaReader.dispatchVideoPicture(MediaReader.java:610) at com.xuggle.mediatool.MediaReader.decodeVideo(MediaReader.java:519) at com.xuggle.mediatool.MediaReader.readPacket(MediaReader.java:475) at com.mycompany.xuggler.H264TranscoderThread.testRTMPPublishH264(H264TranscoderThread.java:68) at com.mycompany.xuggler.H264TranscoderThread.run(H264TranscoderThread.java:77)
Hm... It fails.... O.K. look into the source code.
public void open() { // open the container if (getContainer().open(getUrl(), IContainer.Type.WRITE, mContainerFormat, true, false) < 0) throw new IllegalArgumentException("could not open: " + getUrl()); // inform listeners super.onOpen(new OpenEvent(this)); // note that we should close the container opened here setShouldCloseContainer(true); }Guess from the messages, look into the mContainerFormat more deeper..
MediaWriter(String url, IContainer inputContainer) { super(url, IContainer.make()); // verify that the input container is a readable type if (inputContainer.getType() != IContainer.Type.READ) throw new IllegalArgumentException( "inputContainer is improperly must be of type readable."); // verify that no streams will be added dynamically if (inputContainer.canStreamsBeAddedDynamically()) throw new IllegalArgumentException( "inputContainer is improperly configured to allow " + "dynamic adding of streams."); // record the input container and url mInputContainer = inputContainer; // create format mContainerFormat = IContainerFormat.make(); mContainerFormat.setOutputFormat(mInputContainer.getContainerFormat(). getInputFormatShortName(), getUrl(), null); }Hm, it getting from the reader..... Then maybe....., change the code.
IMediaReader reader = ToolFactory.makeReader(baseURL+this.streamName); reader.open(); IMediaWriter writer = ToolFactory.makeWriter(baseURL+this.transcodedStreamName, reader); reader.addListener(writer); while (reader.readPacket() == null){ do {} while(false); }Yes it works.
Labels:
Xuggler
Monday, January 31, 2011
Live Transcoding using Xuggler with Wowza
I tried to use xuggler for live transcoding with Wowza. Good startpoint is explained at here. Finnaly, it works, but I struggled for a day.
The problem I had was that the ffmpeg do not publish any stream. I saw the Wowza log and found that it connected to server and started getting the stream. But the publishing did not happen.
I used command "ffprobe" to find the issue that ffmpeg did not find audio codec. Followings were messages when I run it. It took around 10 minutes to see the error message.
Oh, I got it. I'm not streaming audio when I start publishing video. And that is the reason why ffmpeg do not start publish any stream. So, I start publishing audio and video at the same time. Yes, it works.
Hm, the issue remains is how to support muting mic. Maybe some tricks are required.
The problem I had was that the ffmpeg do not publish any stream. I saw the Wowza log and found that it connected to server and started getting the stream. But the publishing did not happen.
I used command "ffprobe" to find the issue that ffmpeg did not find audio codec. Followings were messages when I run it. It took around 10 minutes to see the error message.
> ffprobe rtmp://127.0.0.1/live/myStream FFprobe version SVN-r26402-xuggle-4.0.revision.sh, Copyright (c) 2007-2011 the FFmpeg developers built on Jan 31 2011 15:10:13 with gcc 4.1.2 20080704 (Red Hat 4.1.2-48) configuration: --prefix=/usr/local/xuggler --extra-version=xuggle-4.0.revision.sh --extra-cflags=-I/usr/local/xuggler/include --extra-ldflags=-L/usr/local/xuggler/lib --enable-shared --enable-gpl --enable-nonfree --enable-version3 --enable-libx264 --enable-libmp3lame --enable-libvorbis --enable-libtheora --enable-libspeex --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-pthreads libavutil 50.36. 0 / 50.36. 0 libavcore 0.16. 1 / 0.16. 1 libavcodec 52.108. 0 / 52.108. 0 libavformat 52.93. 0 / 52.93. 0 libavdevice 52. 2. 3 / 52. 2. 3 libavfilter 1.74. 0 / 1.74. 0 libswscale 0.12. 0 / 0.12. 0 [flv @ 0xf816210] Estimating duration from bitrate, this may be inaccurate Input #0, flv, from 'rtmp://127.0.0.1/live/myStream': Duration: N/A, start: 0.000000, bitrate: N/A Stream #0.0: Video: flv, yuv420p, 320x240, 1k tbr, 1k tbn, 1k tbc Stream #0.1: Audio: [0][0][0][0] / 0x0000, 0 channels Unsupported codec (id=0) for input stream 1
Oh, I got it. I'm not streaming audio when I start publishing video. And that is the reason why ffmpeg do not start publish any stream. So, I start publishing audio and video at the same time. Yes, it works.
> ffprobe rtmp://127.0.0.1/live/myStream FFprobe version SVN-r26402-xuggle-4.0.revision.sh, Copyright (c) 2007-2011 the FFmpeg developers built on Jan 31 2011 15:10:13 with gcc 4.1.2 20080704 (Red Hat 4.1.2-48) configuration: --prefix=/usr/local/xuggler --extra-version=xuggle-4.0.revision.sh --extra-cflags=-I/usr/local/xuggler/include --extra-ldflags=-L/usr/local/xuggler/lib --enable-shared --enable-gpl --enable-nonfree --enable-version3 --enable-libx264 --enable-libmp3lame --enable-libvorbis --enable-libtheora --enable-libspeex --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-pthreads libavutil 50.36. 0 / 50.36. 0 libavcore 0.16. 1 / 0.16. 1 libavcodec 52.108. 0 / 52.108. 0 libavformat 52.93. 0 / 52.93. 0 libavdevice 52. 2. 3 / 52. 2. 3 libavfilter 1.74. 0 / 1.74. 0 libswscale 0.12. 0 / 0.12. 0 [flv @ 0x10056210] Estimating duration from bitrate, this may be inaccurate Input #0, flv, from 'rtmp://127.0.0.1/live/myStream': Duration: N/A, start: 0.000000, bitrate: N/A Stream #0.0: Video: flv, yuv420p, 320x240, 1k tbr, 1k tbn, 1k tbc Stream #0.1: Audio: nellymoser, 11025 Hz, mono, s16
Hm, the issue remains is how to support muting mic. Maybe some tricks are required.
Subscribe to:
Posts (Atom)