[Live-devel] erratic MJPEG streaming

xavier nikoxan at mixmail.com
Tue Jul 27 21:06:48 PDT 2004


Hi Ross and thank you another time for your advise, your help's become priceless.

As you told me in your last response,

> This is easy: You are trying to simulate streaming motion-JPEG at a
> particular frame rate, so just set these parameters based on this simulated
> frame rate.

My RPVRFramedSource (derived from JPEGVideoSource) class tries to simulate a motion-JPEG
with a few or only one still image. I filled in the parameters the way you told me and now
the play function looks like this:

   fFrameSize = len;
   if (fFrameSize > fMaxSize) 
   {
	fNumTruncatedBytes = fFrameSize - fMaxSize;
	fFrameSize = fMaxSize;
   }
   memmove(fTo, strm, fFrameSize);  
 
    gettimeofday(&fPresentationTime, &quin);
   fDurationInMicroseconds=100000;//10fps
 
   nextTask()
    = envir().taskScheduler().scheduleDelayedTask(0, (TaskFunc*)afterGetting,
						  this);  

but I still got the same problems as usual: vlc gets the streaming parameters correctly,
but a green screen is displayed, whilst my image appears only from time to time. Tried it
with 4 stored frames in disk, which are delivered in order, just to see if the image
displayed would change, and it really does: my 4 images are shown fastly and green screen
again. So the situation is that sometimes I can see the stream correctly, and sometimes a
green screen or nothing appears.

Thought it was a vlc problem, but tried 
openRTSP -m rtsp://217.124.80.191:7070/testStream
and *any* of the jpegs stored can be opened to see what it is being received.

As I am getting a bit of desperate, I send you the code of the server using my
RPVRFramedSource(maybe I got troubled in a silly line, but I cannot find where the problem
lies).
If it worked, could it be considered as an example of JPEGVideoSource using?

Sorry about all this messy code in my post and thank you very much for your help.

Xavier


UsageEnvironment* env;
RTPSink *mjpegSink;
RPVRFramedSource *videoRPVRSource;
 
// To stream using "source-specific multicast" (SSM), uncomment the following:
//#define USE_SSM 1
#ifdef USE_SSM
Boolean const isSSM = True;
#else
Boolean const isSSM = False;
#endif

// To set up an internal RTSP server, uncomment the following:
#define IMPLEMENT_RTSP_SERVER 1
// (Note that this RTSP server works for multicast only)

#ifdef IMPLEMENT_RTSP_SERVER
RTSPServer* rtspServer;
RTCPInstance* audioRTCP;
RTCPInstance* videoRTCP;
#endif

// To stream *only* MPEG "I" frames (e.g., to reduce network bandwidth),
// change the following "False" to "True":
Boolean iFramesOnly = False;

void play(); // forward

void main()
{
  	// Begin by setting up our usage environment:
  	TaskScheduler* scheduler = BasicTaskScheduler::createNew();
  	env = BasicUsageEnvironment::createNew(*scheduler);

  	// Create 'groupsocks' for RTP and RTCP:
  	char* destinationAddressStr
#ifdef USE_SSM
    	= "232.255.42.42";
#else
    	 = "239.255.42.42";
	 
	 
  	// Note: This is a multicast address.  If you wish to stream using
  	// unicast instead, then replace this string with the unicast address
  	// of the (single) destination.  (You may also need to make a similar
  	// change to the receiver program.)
#endif

 	 
  	const unsigned short rtpPortNumVideo = 8888;
  	const unsigned short rtcpPortNumVideo = rtpPortNumVideo+1;
  	const unsigned char ttl = 7; // low, in case routers don't admin scope

  	struct in_addr destinationAddress;
  	destinationAddress.s_addr = our_inet_addr(destinationAddressStr);

 	const Port rtpPortVideo(rtpPortNumVideo);
  	const Port rtcpPortVideo(rtcpPortNumVideo);
	Groupsock rtpGroupsockVideo(*env, destinationAddress, rtpPortVideo, ttl);
	Groupsock rtcpGroupsockVideo(*env, destinationAddress, rtcpPortVideo, ttl);

#ifdef USE_SSM
 
  	rtpGroupsockVideo.multicastSendOnly();
  	rtcpGroupsockVideo.multicastSendOnly();
#endif

	const unsigned maxCNAMElen = 100;
  	unsigned char CNAME[maxCNAMElen+1];
  	gethostname((char*)CNAME, maxCNAMElen);
  	CNAME[maxCNAMElen] = '\0'; // just in case

	const unsigned totalSessionBandwidthVideo = 4500; // in kbps; for RTCP b/w share
 
	// Create a 'MJPEG Video RTP' sink from the RTP 'groupsock':
 	 mjpegSink = JPEGVideoRTPSink::createNew(*env, &rtpGroupsockVideo); 

#ifdef IMPLEMENT_RTSP_SERVER
  	RTCPInstance* videoRTCP =
#endif

    	RTCPInstance::createNew(*env, &rtcpGroupsockVideo,
			      totalSessionBandwidthVideo, CNAME,
			      mjpegSink, NULL /* we're a server */, isSSM);
  	// Note: This starts RTCP running automatically

#ifdef IMPLEMENT_RTSP_SERVER

  	 rtspServer = RTSPServer::createNew(*env,7070);
  	// Note that this (attempts to) start a server on the default RTSP server
  	// port: 554.  To use a different port number, add it as an extra
  	// (optional) parameter to the "RTSPServer::createNew()" call above.
  	if (rtspServer == NULL) {
    	*env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
    	exit();
 	 }
 
  	ServerMediaSession* sms
      	= ServerMediaSession::createNew(*env, "testStream", "My Video Out",
				      "Session streamed by \"this program\"",
					   isSSM);
	sms->addSubsession(PassiveServerMediaSubsession::createNew(*mjpegSink, videoRTCP));


	rtspServer->addServerMediaSession(sms);

  	url_rtsp = rtspServer->rtspURL(sms);
  	*env << "Play this stream using the URL \"" << url_rtsp << "\"\n";
  	 
#endif


  // Finally, start the streaming:
  *env << "Beginning streaming...\n";
  play();

  env->taskScheduler().doEventLoop(); // does not return

}

void  afterPlaying(void* clientData) {
  	// One of the sinks has ended playing.
  	// Check whether any of the sources have a pending read.  If so,
  	// wait until its sink ends playing also:

	 if(videoRPVRSource->isCurrentlyAwaitingData())
	 	return;
	// Now that the sink has ended, close input source,
  	// and start playing again:
  	*env << "...done reading from live input\n";

	mjpegSink->stopPlaying();
      // ensures that is shut down

	Medium::close(videoRPVRSource); 

	// Start playing once again:
 	 play();
}

void  play() {
 
	 videoRPVRSource=RPVRFramedSource::createNew(*env);
	// Finally, start playing the sink.
  	*env << "Beginning to read ..\n";
  	mjpegSink->startPlaying(*videoRPVRSource, afterPlaying, mjpegSink);

}
---------------------------------------------------------
¿Te gustan las apuestas? ¡Pues ahora juega también online! Y buena suerte... http://sorteos.ya.com
Ya.com ADSL Router Wi-Fi: Sólo 29,90 €/mes + IVA*. Router + Antivirus y firewall ¡Gratis! http://acceso.ya.com/adsl/256router



More information about the live-devel mailing list