I am trying to read pixels from a quicktime movie on windows. I am aparently
loading the movie and creating a matching 32 bit per pixel gworld and
finding an interesting time, but the pixels are white.
I am very new to this and may have overlooked something important. It seems
that everything is fine except the actual pixels.
first I call my own function int error = getMovie("filename.mov", movie,
width, height, duration, frames);
to get the movie handle and its size and duration ect
That returns valid values
Then I call GWorldPtr gworld = createGWorld(width,height,pixMapHandle);
to get a gworld. It is always 32 bit no matter what the movie might
originally is. I need it in that format.
Then I call SetMovieGWorld(movie, gworld, GetGWorldDevice(gworld)); to bind
the movie to the gworld.
Next I call my own function renderNextFrame(movie); which finds the next
interesting time and renders it.. or so I hope.
After all this I et the baseaddress of the pixmap and look at the bytes,
which are all 255.
It is next to impossible (for me) to tell where the error is, but I append
all the code of the sample app, in which I have declared the above mentioned
functions. It would be greatly appresiated if someone would take a quick
look at the code and point out the error.
I _assume_ that the problem is related to locking the pixmap or the setting
of a new time and rendering. When exactly should I lock, and should I not
unlock as well?
-------------------
void main()
{
OSErr errCode = InitializeQTML(0);
EnterMovies();
Movie movie;
int width;
int height;
float duration;
int frames;
int error = getMovie("c:\\a.mov", movie, width, height, duration, frames);
PixMapHandle pixMapHandle;
GWorldPtr gworld = createGWorld(width,height,pixMapHandle);
SetMovieGWorld(movie, gworld, GetGWorldDevice(gworld));
renderNextFrame(movie);
Ptr data = GetPixBaseAddr(pixMapHandle);
for(int i=0;i<100;i++) //just looking at the 25 first pixels
{
unsigned char a = *((unsigned char*)data++);
unsigned char r = *((unsigned char*)data++);
unsigned char g = *((unsigned char*)data++);
unsigned char b = *((unsigned char*)data++);
}
getch();
}
int getMovie(char* fileName, Movie& movie, int& width, int& height, float&
duration, int& frames)
{
FSSpec spec;
short refNumber=0;
OSErr errCode = NativePathNameToFSSpec(fileName, &spec, 0);
if(errCode) return 2;
errCode = OpenMovieFile(&spec,&refNumber, fsRdPerm);
if(errCode) return 3;
errCode = NewMovieFromFile(&movie, refNumber, 0,NULL,0,0);
if(errCode) return 4;
TimeValue tv = GetMovieDuration(movie);
Rect r;
GetMovieBox(movie, &r);
width=r.right;
height=r.bottom;
TimeScale ts = GetMovieTimeScale(movie);//fps
Fixed ffr=GetMoviePreferredRate(movie);
duration = (float)tv/(float)ts;
Track track = GetMovieIndTrackType(movie,1, 'vfrr',
movieTrackCharacteristic);
Media media = GetTrackMedia(track);
frames = GetMediaSampleCount(media);
return 0;
}
GWorldPtr createGWorld(int width, int height, PixMapHandle &pixMapHandle)
{
GWorldPtr gworld;
Rect bounds;
OSErr errCode;
bounds.top = bounds.left = 0;
bounds.right = width;
bounds.bottom = height;
errCode = QTNewGWorld(&gworld,32,&bounds,NULL,NULL,NULL);
if(errCode) return 0;
//clear the first frame.. is this nessesary?
LockPixels(GetGWorldPixMap(gworld));
SetGWorld(gworld,NULL);
Rect rect;
rect.left = rect.top = 0;
rect.right = width;
rect.bottom = height;
EraseRect(&rect);
pixMapHandle = GetGWorldPixMap(gworld);
return gworld;
}
void renderNextFrame(Movie movie)
{
short flags = nextTimeMediaSample;
OSType whichMediaType = 'vide';
//flags |= nextTimeEdgeOK;
TimeValue movieTime=0;
TimeValue duration;
GetMovieNextInterestingTime(movie,
flags,
1,
&whichMediaType,
movieTime,
0,
&movieTime,
&duration);
SetMovieTimeValue(movie,movieTime);
MoviesTask(movie,0);
}
William Bertelsen - 19 Apr 2007 11:51 GMT
It seems that I need to call StartMovie() before reading pixels. I have not
tested it very much yet, but the colors that I get, they are faily accurate
looking now. A redish movie has redish colors and a bluish one is sorta
blue. If it is correct pixels, which I wil test later, it works now, but...
why do I need to StartMovie? The samples I have seen, which are rarely
complete programs, they never call startmovie.
Jan E. Schotsman - 19 Apr 2007 16:26 GMT
> It seems that I need to call StartMovie() before reading pixels. I have
> not tested it very much yet, but the colors that I get, they are faily
> accurate looking now. A redish movie has redish colors and a bluish one
> is sorta blue. If it is correct pixels, which I wil test later, it
> works now, but... why do I need to StartMovie? The samples I have seen,
> which are rarely complete programs, they never call startmovie.
You need to call SetMovieActive.
Also call MoviesTask after acter calling SetMovieTime.
You can set a callback on MoviesTask that does something with the
image, then steps to the next frame/time.
Jan E.
William Bertelsen - 19 Apr 2007 16:55 GMT
> You need to call SetMovieActive.
> Also call MoviesTask after acter calling SetMovieTime.
> You can set a callback on MoviesTask that does something with the image,
> then steps to the next frame/time.
Thanks! That works as well.
I called the moviesTask before as well, but I needed either startmovie or
setmovieactive.
I find little or no info on the two and what exactly the difference is.
What I want is generally just to open a movie and get the frames one by one.
Rather fast and with controll than quick and without. I preload the data to
memory and deal with it from there, so it is fine to set frame 0, read the
pixels, set frame 1 etc without callbacks, since I will not be doing
anything else when reading the pixels.
Is this what I get from opening the movie, setting the gworld , setting
active and interesting time and reading the pixmap and then next
interesting, or arethere some side efects to this method? I suspected tht
StartMovie might actually start up some background processing which ran the
frames, but I could not really see that that hapened.
Jan E. Schotsman - 27 Apr 2007 20:06 GMT
>> You need to call SetMovieActive.
>> Also call MoviesTask after acter calling SetMovieTime.
[quoted text clipped - 5 lines]
> or setmovieactive.
> I find little or no info on the two and what exactly the difference is.
From the documentation for StartMovie accessible in Xcode (Mac
programming tool):
You are not required to call this function to start a movie. It is
included in the QuickTime API for convenience. Before playing the
movie, the Movie Toolbox makes the movie active, prerolls the movie,
and sets the movie to its preferred playback rate. You can use
SetMoviePreferredRate (III-1740) to change this setting.
With apologies for the late reaction. I forgot about this thread.
Jan E.