• SEARCH
  • DOWNLOADS
  • MY ACCOUNT
  • Buy (0)
  • CONTACT
  • Free Trial
Wowza Logo
  • PRODUCTS
  • DEVELOPER
  • SOLUTIONS
  • PRICING
  • RESOURCES
  • SUPPORT
  • My Account
  • Buy (0)
  • SEARCH
  • Ask a question
  • Forums
    • Wowza ClearCaster
    • Wowza Streaming Engine
    • Wowza Streaming Cloud
    • Wowza Player
    • Wowza GoCoder SDK
    • Wowza Developer Dojo
    • Topics
    • Questions
    • Articles
    • Users
    • Badges
  • Sign in
  • Community Home /
  • Wowza Streaming Engine /
  • Wowza Transcoder /
avatar image
Question by Karel Boek-Senior Consultant · Aug 26, 2015 at 09:34 AM · wowza transcoder

onGrabFrame is never called

After having read this post and this article, I wrote and compiled the code below to grab a frame from a stream every x seconds. However, the GrabResult.onGrabFrame is never called. I have verified that the sourceVideo.grabFrame(new GrabResult()) is getting called every 4 secs.

Can anyone help me find why onGrabFrame isn't called?

WSE 4.2 (build 15089); Win 10 (64-bit); Oracle JDK 1.8.0_45

PS: I know it would maybe better to use a TranscoderCreateNotifier and TranscoderActionNotifier, so that the Runnable isn't started before the transcoder is actually processing video, but that's not the cause of the problem - I tested that.

Disclaimer: I'm Authorized Wowza Consultant, doing Wowza configuration and development on a daily basis

package org.acme.wms.modules;
import com.wowza.wms.application.IApplicationInstance;
import com.wowza.wms.application.WMSProperties;
import com.wowza.wms.module.ModuleBase;
import com.wowza.wms.stream.IMediaStream;
import com.wowza.wms.stream.IMediaStreamActionNotify2;
import com.wowza.wms.transcoder.model.ITranscoderFrameGrabResult;
import com.wowza.wms.transcoder.model.LiveStreamTranscoder;
import com.wowza.wms.transcoder.model.TranscoderNativeVideoFrame;
import com.wowza.wms.transcoder.model.TranscoderStream;
import com.wowza.wms.transcoder.model.TranscoderStreamSourceVideo;
public class ModuleGrabFrame extends ModuleBase {
	
	@SuppressWarnings("unchecked")
	public void onStreamCreate(IMediaStream stream) {
		
		IMediaStreamActionNotify2 actionNotify = new StreamListener();
		WMSProperties props = stream.getProperties();
		
		synchronized (props) {
			props.put("streamActionNotifier", actionNotify);
		}
		
		stream.addClientListener(actionNotify);
	}
	
	public void onStreamDestroy(IMediaStream stream) {
		
		IMediaStreamActionNotify2 actionNotify = null;
		WMSProperties props = stream.getProperties();
		
		synchronized (props) {
			actionNotify = (IMediaStreamActionNotify2)stream.getProperties().get("streamActionNotifier");
		}
		
		if (actionNotify != null) {
			stream.removeClientListener(actionNotify);
		}
	}
	
	private final class StreamListener implements IMediaStreamActionNotify2 {
		
		// ...
		
		@Override
		public void onPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) {
			new FrameGrabber(stream).run();
		}
		
		// ... rest of the IMediaStreamActionNotify2 implementation omitted 
	}
	
	private final class FrameGrabber implements Runnable {
		
		private IMediaStream _stream;
		private boolean _running;
		
		public FrameGrabber(IMediaStream stream) {
			_stream = stream;
		}
		@Override
		public void run() {
			while (_running) {
				LiveStreamTranscoder liveStreamTranscoder = (LiveStreamTranscoder) _stream.getLiveStreamTranscoder("transcoder");
				
				if (liveStreamTranscoder == null) {
					getLogger().warn("No LiveStreamTranscoder available (yet)");
					return;
				}
				
				TranscoderStream transcodingStream = liveStreamTranscoder.getTranscodingStream();
				
	            if (transcodingStream == null) {
	                getLogger().warn("No TranscoderStream available");
	                return;
	            }
	            
	            TranscoderStreamSourceVideo sourceVideo = transcodingStream.getSource().getVideo();
	            
	            if (sourceVideo == null) {
	            	getLogger().warn("No TranscoderStreamSourceVideo available");
	            	return;
	            }
	            
	            sourceVideo.grabFrame(new GrabResult());
	            
	            try {
					Thread.sleep(4000);
				} catch (InterruptedException e) {
					getLogger().error("Exception when trying to sleep", e);
					_running = false;
				}
			}
		}
	}
	
	public class GrabResult implements ITranscoderFrameGrabResult {
		@Override
		public void onGrabFrame(TranscoderNativeVideoFrame nativeFrame) {
			getLogger().info("Grabbing frame now ...");
		}
	}
}
The transcoder template is as follows
<?xml version="1.0" encoding="UTF-8"?>
<Root>
	<Transcode>
		<Description></Description>
		<Decode>
			<Video>
				<Implementation>default</Implementation>
				<Deinterlace>false</Deinterlace>
			</Video>
		</Decode>
		<Encodes>
			<Encode>
				<Name>Simple</Name>
				<Enable>true</Enable>
				<Description></Description>
				<StreamName>mp4:${SourceStreamName}_simple</StreamName>
				<Video>
					<Codec>H.264</Codec>
					<Implementation>QuickSync</Implementation>
					<GPUID>-1</GPUID>
					<Profile>baseline</Profile>
					<Bitrate>800000</Bitrate>
					<KeyFrameInterval>
						<FollowSource>true</FollowSource>
						<Interval>0</Interval>
					</KeyFrameInterval>
					<FrameSize>
						<FitMode>match-source</FitMode>
						<Width>0</Width>
						<Height>0</Height>
						<Crop>0,0,0,0</Crop>
						<SourceRectangle></SourceRectangle>
					</FrameSize>
				</Video>
				<Audio>
					<Codec>AAC</Codec>
					<Bitrate>64000</Bitrate>
				</Audio>
			</Encode>
		</Encodes>
	</Transcode>
</Root>
Comment

People who like this

0 Show 0
10 |600 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image

Answer by Roger Littin · Sep 09, 2015 at 01:44 PM

Hi Karel,

There are a few issues with your workflow:

		@Override
		public void onPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) {
			new FrameGrabber(stream).run();
		}


I'm assuming you are wanting to spawn a new thread for your Runnable. All this is doing is creating a new FrameGrabber object and calling its run method in the current thread. If the encoder is waiting for a response from the server for the publish request (which it should be doing), before sending any stream data, it won't receive this until your run method returns and the onPublish method can return.

You need to create a separate thread.

		@Override
		public void onPublish(IMediaStream stream, String streamName, boolean isRecord, boolean isAppend) {
			(new Thread(new FrameGrabber(stream))).start();
		}


The transcoder startup is triggered when the first stream data is received from the encoder. Because you are doing this check in the same thread that onPublish is running, the encoder shouldn't have sent any steam data at this point. When you do the check, no data has arrived to trigger the transcoder startup and then you are returning from your run method instead of looping.

I haven't tested it but the following should work better.

		@Override
		public void run() {
			long sleepTime = 100;
			while (_running) {
				try {
					Thread.sleep(sleepTime);
				} catch (InterruptedException e) {
					getLogger().error("Exception when trying to sleep", e);
					_running = false;
					break;
				}
				LiveStreamTranscoder liveStreamTranscoder = (LiveStreamTranscoder) _stream.getLiveStreamTranscoder("transcoder");
				
				if (liveStreamTranscoder == null) {
					getLogger().warn("No LiveStreamTranscoder available (yet)");
					continue;
				}
				
				TranscoderStream transcodingStream = liveStreamTranscoder.getTranscodingStream();
				
				if (transcodingStream == null) {
					getLogger().warn("No TranscoderStream available");
					continue;
				}
	            
				TranscoderStreamSourceVideo sourceVideo = transcodingStream.getSource().getVideo();
	            
				if (sourceVideo == null) {
					getLogger().warn("No TranscoderStreamSourceVideo available");
					continue;
				}
	            		
				getLogger().info("ready to grab a frame");
				sourceVideo.grabFrame(new GrabResult());
				sleepTime = 4000;
			}
		}


Using the proper event listeners is the best way to go and then you will be sure that everything is ready when you want to start grabbing frames.

Roger.
Comment

People who like this

0 Show 0 · Share
10 |600 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

1 Person is following this question.

avatar image

Related Questions

configure Quick Sync accelerated encoding on Linux problem on EC2 1 Answer

Doubt about PassThru on Wowza Transcoder Add-On 1 Answer

Auto redirect encoder to server wi least active transcoding sessions 1 Answer

Live Stream Transcoding output to Multicast 1 Answer

Ip camera video delay after G.711 transcoding 4 Answers

Hot Topics
  • AWS Hosting
  • Mobile SDK
  • Deployment Options
  • Load Balancing
  • Content Security
Product Sign-in
  • Wowza Streaming Cloud
  • Wowza Player
Under the Hood
  • Developer Tools
  • Wowza System Status
  • Test Players
  • Developer IDE
Resellers
  • Find a Reseller
  • Reseller Portal
  • Become a Reseller
Company
  • About Us
  • Blog
  • News
  • Events
  • Careers
  • Customers
  • Partners
  • Contact Us
Stay Connected
Get Monthly Newsletter
Select a Language
  • English
    • English
    • Español
    • 日本語
    • 한국어
    • हिन्दी भाषा
    • 中文
    • русский язык

© 2005–2019 Wowza Media Systems, LLC. All rights reserved.   Terms | Privacy | Trademarks | Legal


Enterprise
Social Q&A

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Create an article
  • Forums
  • Wowza ClearCaster
  • Wowza Streaming Engine
  • Wowza Streaming Cloud
  • Wowza Player
  • Wowza GoCoder SDK
  • Wowza Developer Dojo
  • Explore
  • Topics
  • Questions
  • Articles
  • Users
  • Badges