[osg-users] problem of qt plugin for rtsp real time streaming

hui opencvyang at yahoo.com
Sun Jul 6 00:12:24 PDT 2008


Hi, 

Sorry I forget I should send plain text email so my previous email is totally cannot be read. 
Here is my question. I try to make rtsp work with osg quicktime plugin. According one user's idea, I make 
some change in qt plugin as follows:
1. I add load movie from url: 

if (CFURLRef urlRef = CFURLCreateWithBytes(NULL, (const UInt8 *)url, strlen(url), kCFStringEncodingUTF8, NULL)) { 
			Handle  dataRef;
			OSType  dataRefType;
			error = QTNewDataReferenceFromCFURL(urlRef, 0, &dataRef, &dataRefType); 
			if (error == noErr) {
				error = NewMovieFromDataRef(movie, newMovieIdleImportOK, NULL, dataRef, dataRefType); 
				error = GetMoviesError();
			}
			
			CFRelease(urlRef);
		}

2. 2. open it with a function as prepreroolMovie ( quicktime api said this is required for streaming): 

err = MakeMovieFromURL(filename.c_str(),&_movie);
		// add prepreroll
		
		err = PrePrerollMovie(_movie, 0, GetMoviePreferredRate(_movie),
			                                        NewMoviePrePrerollCompleteProc(MovieData::MoviePrePrerollCompleteProc),
							  (void *)this); 

<< here get problem, if http, it is ok, but rtsp PrePrerollMovie() will return -1.  
What I cannot understand is: I implement this with glut and it never get an error. 


// simpleQTtest.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "simpleQTtest.h"
#include <GL/glew.h>

#include <glvu.hpp>
#include <ppm.hpp>

#include <GL/glut.h>

#include "QTML.h"
#include "Movies.h"
#include "ImageCompression.h"
#include "MacErrors.h"


GLVU glvu;

#define MAX_LOADSTRING 100


Movie theMovie;

Rect box;

GLuint textureUnit; 
unsigned char *image; 
int width, height;

void userDisplayFunc0()
{
  glvu.BeginFrame();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //glColor3f(1,0,0);
    //glutSolidTorus(0.25,1,32,64);
	glEnable(GL_TEXTURE_2D); 
	glBindTexture(GL_TEXTURE_2D, textureUnit); 
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,image); 


	glBegin(GL_QUADS); 
			glTexCoord2d(0.0, 0.0);		glVertex3d(-0.5, -0.5, 0); 
			glTexCoord2d(0.0, 1.0); 	glVertex3d(-0.5, 0.5, 0); 
			glTexCoord2d(1.0, 1.0);		glVertex3d(0.5, 0.5, 0); 
			glTexCoord2d(1.0, 0.0);		glVertex3d(0.5, -0.5, 0); 
	glEnd(); 
  glvu.EndFrame();
}


void loadPPMImage()
{
  
   LoadPPM("sample.ppm", image, width, height);  
}

void UpdateMovieGWorld(Movie m)
{
	CGrafPtr port;
	GDHandle dev;
	GetMovieGWorld(m,&port,&dev);

	Rect box;
	GetMovieNaturalBoundsRect(m,&box);

	MacOffsetRect (&box, -box.left, -box.top);
	SetMovieBox (m, &box);

	int width=box.right;
	int height=box.bottom;

	GWorldPtr movieGWorld;
	void* pixels=malloc(width*height*4);

	NewGWorldFromPtr(&movieGWorld,k32BGRAPixelFormat,&box,0,0,0,(Ptr)pixels,width*4);

	SetMovieGWorld (m, (CGrafPtr)movieGWorld, nil);

	if (port && !dev)
	{
		pixels=port->portPixMap[0]->baseAddr;
		DisposeGWorld(port);
		free(pixels);
	}
}

void MyMoviePrePrerollCompleteProc(Movie theMovie, OSErr prerollErr,
								   void *refcon)
{
	Fixed rate=GetMoviePreferredRate(theMovie);
	//PrerollMovie(theMovie,0,rate);
	SetMovieRate(theMovie,rate);
	StartMovie(theMovie);
}

OSErr MyMovieDrawingCompleteProc(Movie theMovie, long refCon)
{
	

	CGrafPtr port;
	GDHandle dev;
	GetMovieGWorld(theMovie,&port,&dev);

	char* pixels=port->portPixMap[0]->baseAddr;
	int pixels_width=port->portPixMap[0]->bounds.right;
	int pixels_height=port->portPixMap[0]->bounds.bottom;


	image = (unsigned char *) pixels; 
	width = pixels_width; 
	height = pixels_height; 
        userDisplayFunc0(); 	

	return noErr;
}


bool LoadMovieFromPath(Movie* m, const char* thePath)
{
	char fullpath[255];
	strcpy(fullpath,thePath);
	c2pstr(fullpath);

	short theFile = 0;
	FSSpec sfFile;

	FSMakeFSSpec (0, 0L, (ConstStr255Param)fullpath, &sfFile);

	int err=OpenMovieFile (&sfFile, &theFile, fsRdPerm);
	if (err!=noErr)
		return false;

	err=NewMovieFromFile (m, theFile, nil, nil, newMovieActive,
		nil);

	CloseMovieFile (theFile);

	if (err!=noErr)
		return false;

	UpdateMovieGWorld(*m);

	MyMoviePrePrerollCompleteProc(*m,0,0);

	return true;
}

bool LoadMovieFromURL(Movie* m, const char* url)
{
	
	OSStatus  error = memFullErr;
	if (CFURLRef urlRef = CFURLCreateWithBytes(NULL, (const UInt8 *)url, strlen(url), kCFStringEncodingUTF8, NULL)) { 
		Handle  dataRef;
		OSType  dataRefType;
		error = QTNewDataReferenceFromCFURL(urlRef, 0, &dataRef, &dataRefType); 
		if (error == noErr) 
			error = NewMovieFromDataRef(m, newMovieActive | newMovieAsyncOK, NULL, dataRef, dataRefType); 
		CFRelease(urlRef);
	}

	

	//SetMovieDrawingCompleteProc(*m, movieDrawingCallWhenChanged,  
	//	 MyMovieDrawingCompleteProc, 0 /*refCon*/);//,

	/*SetMoviePlayHints(*m, hintsAllowDynamicResize,
		hintsAllowDynamicResize);*/
	Fixed rate = GetMoviePreferredRate(*m); 

	error=PrePrerollMovie(*m, 0, GetMoviePreferredRate(*m),
		NewMoviePrePrerollCompleteProc(MyMoviePrePrerollCompleteProc), //,
		(void *)0L);


	UpdateMovieGWorld(*m);

	

	
    return true;



}






void idle0()
{
	if(!IsMovieDone(theMovie))
	{
	Rect r;
	GetMovieNaturalBoundsRect(theMovie,&r);
	if (r.right!=box.right || r.bottom!=box.bottom)
	{
		box.right=r.right;
		box.bottom=r.bottom;
		UpdateMovieGWorld(theMovie);
	}


	
	MoviesTask (theMovie, 0);

    CGrafPtr port;
	GDHandle dev;
	GetMovieGWorld(theMovie,&port,&dev);

	char* pixels=port->portPixMap[0]->baseAddr;
	int pixels_width=port->portPixMap[0]->bounds.right;
	int pixels_height=port->portPixMap[0]->bounds.bottom;


	image = (unsigned char *) pixels; 
	width = pixels_width; 
	height = pixels_height; 
    userDisplayFunc0(); 




	Sleep(1);
	}

}

void initTexture()
{
	loadPPMImage(); // read image first. 
	glGenTextures(1, &textureUnit);
	glBindTexture(GL_TEXTURE_2D, textureUnit);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,image); 
	glBindTexture(GL_TEXTURE_2D, 0); 
}

// just leave one main function here then add glvu 

int main()
{
	
	OSErr err;
	err = InitializeQTML(0);//

	err = EnterMovies ();

	// check ver
	long version;
	OSErr result;

	result = Gestalt(gestaltQuickTime,&version);
	if ((result == noErr) && (version >= 0x05020000))
	{
		/* we have version 5.0.2 or later */
	}
	else
		return 0;

	// get the movie from url or file path
	

	const char* url="rtsp://141.161.16.105:554/igp/isip2of5011206.mov";
	
	if (!LoadMovieFromURL(&theMovie,url))
		return 0;

	//SetMovieDrawingCompleteProc(theMovie,movieDrawingCallWhenChanged,   MyMovieDrawingCompleteProc, 0/*refCon*/);

	
	Rect box2; 
	GetMovieNaturalBoundsRect(theMovie,&box);

	GetMovieBox(theMovie, &box2); 

	SetMovieRate(theMovie, 0); 

	float timeScale = GetMovieTimeScale(theMovie); 
	DWORD bias=GetTickCount();





	glvu.Init("Quicktime Basic Example",
		GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA,
		50,50,512,512);

	GLenum erra = glewInit();
	if (GLEW_OK != erra)
	{
		/* Problem: glewInit failed, something is seriously wrong. */
		///fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
		//...
	}



	//glEnable(GL_LIGHTING);
	//glEnable(GL_LIGHT0);
	//glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_DEPTH_TEST);

	initTexture(); 

	glutDisplayFunc(userDisplayFunc0);
	glutIdleFunc(idle0); 

	Vec3f ModelMin(-1,-1,-1), ModelMax(1,1,1); 
	Vec3f LookAtCntr( ModelMin+ModelMax ); LookAtCntr*=0.5;
	Vec3f mintoCtr( LookAtCntr - ModelMin );
	Vec3f Up(0,1,0);
	Vec3f Eye(LookAtCntr - 3*(mintoCtr - Up * (mintoCtr * Up) ));
	float Yfov = 45;
	float Aspect = 1;     // WIDTH OVER HEIGHT
	float Near = 0.1f;    // NEAR PLANE DISTANCE RELATIVE TO MODEL DIAGONAL LENGTH
	float Far = 10.0f;    // FAR PLANE DISTANCE (ALSO RELATIVE)
	glvu.SetAllCams(ModelMin,ModelMax, Eye,LookAtCntr,Up, Yfov,Aspect, Near,Far);

	//--------------------------------------------------------------------------
	// (3) start the viewer event loop.
	//--------------------------------------------------------------------------

	glutMainLoop();




	return 0; 
}


you can see I use exactly same code, but at here the function:
error=PrePrerollMovie(*m, 0, GetMoviePreferredRate(*m),NewMoviePrePrerollCompleteProc(MyMoviePrePrerollCompleteProc), //,(void *)0L);
<< never return -1 error. 
<< beside, this example cannot make "http" working because of buffer conflict but 
<< that is another issue.  
I check the qt plugin code, looks nothing can affect the PrePrerollMovie function, 
So, why rtsp cannot work with osg? 
There is some setting in loadURL like: newMovieIdleImportOK and newMovieActive | newMovieAsyncOK, but even I change it still doesn't work.  
Since I am not familiar with quicktime API, it really confused me. 

Thanks for any help.  


Hui 




      



More information about the osg-users mailing list