lms-video/Gem/plugins/filmDarwin/filmDarwin.cpp
Santi Noreña e85d191b46 - Reestructuración de ficheros y directorios general
- merge v0.01 --> Añadido fileselector
- Añadidas fuentes de Gem y Pure Data
- pix2jpg incluído en Gem. Archivos de construcción de Gem modificados.
- Añadido fichero ompiling.txt con instrucciones de compilación
2013-02-04 18:00:17 +01:00

358 lines
10 KiB
C++

////////////////////////////////////////////////////////
//
// GEM - Graphics Environment for Multimedia
//
// zmoelnig@iem.kug.ac.at
//
// Implementation file
//
// Copyright (c) 1997-1999 Mark Danks.
// Copyright (c) Günther Geiger.
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
// Copyright (c) 2002 James Tittle & Chris Clepper
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
//
/////////////////////////////////////////////////////////
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "filmDarwin.h"
#ifdef HAVE_CARBONQUICKTIME
#include "plugins/PluginFactory.h"
#include "Gem/RTE.h"
#include "Gem/Properties.h"
using namespace gem::plugins;
REGISTER_FILMFACTORY("Darwin", filmDarwin);
/////////////////////////////////////////////////////////
//
// filmDarwin
//
/////////////////////////////////////////////////////////
// Constructor
//
/////////////////////////////////////////////////////////
filmDarwin :: filmDarwin(void) :
m_wantedFormat(GL_YUV422_GEM),
m_auto(false),
m_numFrames(-1), m_numTracks(-1),
m_curFrame(-1), m_lastFrame(-1),
m_movie(NULL),
m_srcGWorld(NULL),
m_movieTime(0),
m_movieTrack(0),
m_movieMedia(0),
m_timeScale(0),
m_durationf(0.),
m_fps(1.)
{}
////////////////////////////////////////////////////////
// Destructor
//
/////////////////////////////////////////////////////////
filmDarwin :: ~filmDarwin(void)
{
close();
}
void filmDarwin :: close(void)
{
if(m_srcGWorld){
::DisposeMovie(m_movie);
::DisposeGWorld(m_srcGWorld);
m_srcGWorld = NULL;
}
}
/////////////////////////////////////////////////////////
// open the file
//
/////////////////////////////////////////////////////////
bool filmDarwin :: open(const std::string filename, const gem::Properties&wantProps)
{
double d;
if(wantProps.get("colorspace", d) && d>0) {
m_wantedFormat=d;
}
FSSpec theFSSpec;
OSErr err = noErr;
FSRef ref;
Rect m_srcRect;
long m_rowBytes;
OSType whichMediaType = VisualMediaCharacteristic;
short flags = nextTimeMediaSample + nextTimeEdgeOK;
short refnum = 0;
OSType pixelformat=0;
long hints;
Track movieTrack;
Media trackMedia;
if(filename.empty()) {
goto unsupported;
} else {
err = ::FSPathMakeRef((const UInt8*)filename.c_str(), &ref, NULL);
err = ::FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
if (err) {
//error("filmDarwin: Unable to find file: %s", filename.c_str());
goto unsupported;
}
}
err = ::OpenMovieFile(&theFSSpec, &refnum, fsRdPerm);
if (err) {
//error("filmDarwin: Couldn't open the movie file: %#s (%d)", theFSSpec.name, err);
if (refnum) ::CloseMovieFile(refnum);
goto unsupported;
}
::NewMovieFromFile(&m_movie, refnum, NULL, NULL, newMovieActive, NULL);
if (refnum) ::CloseMovieFile(refnum);
// m_curFrame = -1;
if(m_curFrame==-1)m_curFrame=-2;
m_lastFrame=-1;
m_numTracks = (int)GetMovieTrackCount(m_movie);
verbose(1, "filmDarwin: m_numTracks = %d",(int)m_numTracks);
// Get the length of the movie
long movieDur, movieScale;
movieDur = (long)GetMovieDuration(m_movie);
movieScale = (long)GetMovieTimeScale(m_movie);
verbose(1, "Movie duration = %d timescale = %d timebase = %d",movieDur, movieScale, (long)GetMovieTimeBase(m_movie));
movieTrack = GetMovieIndTrackType(m_movie,
1,
VideoMediaType,
movieTrackMediaType); //get first video track
trackMedia = GetTrackMedia(movieTrack);
m_numFrames= GetMediaSampleCount(trackMedia);
if(m_numFrames>0) {
m_durationf = static_cast<double>(movieDur)/static_cast<double>(m_numFrames);
m_fps=static_cast<double>(m_numFrames)*static_cast<double>(movieScale)/static_cast<double>(movieDur);
} else {
m_numFrames=-1;
m_fps=30.f;
m_durationf=static_cast<double>(movieScale)/m_fps;
}
verbose(1, "numFrames= %d...%f", (int)m_numFrames, (float)m_durationf);
// Get the bounds for the movie
::GetMovieBox(m_movie, &m_srcRect);
OffsetRect(&m_srcRect, -m_srcRect.left, -m_srcRect.top);
SetMovieBox(m_movie, &m_srcRect);
m_image.image.xsize = m_srcRect.right - m_srcRect.left;
m_image.image.ysize = m_srcRect.bottom - m_srcRect.top;
verbose(1, "rect rt:%d lt:%d", m_srcRect.right, m_srcRect.left);
verbose(1, "rect top:%d bottom:%d", m_srcRect.top, m_srcRect.bottom);
verbose(1, "movie size x:%d y:%d", m_image.image.xsize, m_image.image.ysize);
switch(m_wantedFormat) {
case 0: // if no other format is requested, use YUV
case GL_YCBCR_422_APPLE:
m_image.image.format = m_wantedFormat;
hints |= hintsHighQuality | hintsDeinterlaceFields;
pixelformat=k422YpCbCr8CodecType;
break;
default:
m_image.image.format = GL_BGRA_EXT;
hints |= hintsHighQuality;
pixelformat=k32ARGBPixelFormat;
break;
}
m_image.image.setCsizeByFormat();
m_image.image.data = new unsigned char [m_image.image.xsize*m_image.image.ysize*m_image.image.csize];
m_rowBytes = m_image.image.xsize * m_image.image.csize;
SetMoviePlayHints(m_movie, hints, hints);
err = QTNewGWorldFromPtr( &m_srcGWorld,
pixelformat,
&m_srcRect,
NULL,
NULL,
0,
m_image.image.data,
m_rowBytes);
if (err) {
//error("filmDarwin: Couldn't make QTNewGWorldFromPtr %d", err);
goto unsupported;
}
m_movieTime = 0;
// *** set the graphics world for displaying the movie ***
::SetMovieGWorld(m_movie, m_srcGWorld, GetGWorldDevice(m_srcGWorld));
::MoviesTask(m_movie, 0); // *** this does the actual drawing into the GWorld ***
return true;
unsupported:
return false;
}
/////////////////////////////////////////////////////////
// render
//
/////////////////////////////////////////////////////////
pixBlock* filmDarwin :: getFrame(void){
CGrafPtr savedPort;
GDHandle savedDevice;
Rect m_srcRect;
PixMapHandle m_pixMap;
::GetGWorld(&savedPort, &savedDevice);
::SetGWorld(m_srcGWorld, NULL);
::GetMovieBox(m_movie, &m_srcRect);
m_pixMap = ::GetGWorldPixMap(m_srcGWorld);
// get the next frame of the source movie
short flags = nextTimeStep;
OSType whichMediaType = VisualMediaCharacteristic;
TimeValue duration;
/* check whether we reached the end of the clip */
if (IsMovieDone(m_movie)) {
GoToBeginningOfMovie(m_movie);
return NULL;
}
if(m_numFrames<0) {
/* the opened media doesn't support seeking
* so we return the next frame, if a new frame was requested
* and the last frame if no new frame was requested
*/
m_movieTime = GetMovieTime(m_movie, NULL);
if(m_curFrame<0 && m_lastFrame<0) {
m_curFrame=0;
}
/* if we have a valid curFrame (>=0) and curFrame progresses (curFrame!=lastFrame), get the next image
* always get the image, if lastFrame<0
*/
if(m_curFrame!=m_lastFrame) {
m_image.newimage=1;
SetMovieRate(m_movie,X2Fix(1.0));
} else {
m_image.newimage=0;
SetMovieRate(m_movie,X2Fix(0.0));
}
MoviesTask(m_movie, 0); // *** this does the actual drawing into the GWorld ***
m_lastFrame=m_curFrame;
return &m_image;
}
//check for last frame to loop the clip
if (m_curFrame >= m_numFrames){
return NULL;
m_curFrame = 0;
m_movieTime = 0;
}
m_movieTime = static_cast<long>(static_cast<double>(m_curFrame) * m_durationf);
m_movieTime-=9; //total hack!! subtract an arbitrary amount and have nextinterestingtime find the exact place
//check for -1
if (m_movieTime < 0) m_movieTime = 0;
// if this is the first frame, include the frame we are currently on
if (m_curFrame == 0) flags |= nextTimeEdgeOK;
// if (m_auto) {
if (1) {
::GetMovieNextInterestingTime(m_movie,
flags,
1,
&whichMediaType,
m_movieTime,
0,
&m_movieTime,
// NULL);
&duration);
flags = 0;
flags = nextTimeStep;
// m_curFrame++;
}
// set the time for the frame and give time to the movie toolbox
SetMovieTimeValue(m_movie, m_movieTime);
MoviesTask(m_movie, 0); // *** this does the actual drawing into the GWorld ***
m_image.newimage=(m_lastFrame != m_curFrame);
m_lastFrame=m_curFrame;
return &m_image;
}
film::errCode filmDarwin :: changeImage(int imgNum, int trackNum){
m_curFrame=imgNum;
// return 0;
return film::SUCCESS;
}
///////////////////////////////
// Properties
bool filmDarwin::enumProperties(gem::Properties&readable,
gem::Properties&writeable) {
readable.clear();
writeable.clear();
gem::any value;
value=0.;
readable.set("frames", value);
readable.set("tracks", value);
readable.set("width", value);
readable.set("height", value);
readable.set("fps", value);
writeable.set("auto", value);
return false;
}
void filmDarwin::setProperties(gem::Properties&props) {
double d;
if(props.get("auto", d)) {
m_auto=(d>=0.5);
}
}
void filmDarwin::getProperties(gem::Properties&props) {
std::vector<std::string> keys=props.keys();
gem::any value;
double d;
unsigned int i=0;
for(i=0; i<keys.size(); i++) {
std::string key=keys[i];
props.erase(key);
if("frames"==key) {
d=m_numFrames;
value=d; props.set(key, value);
}
if("tracks"==key) {
d=m_numTracks;
value=d; props.set(key, value);
}
if("width"==key) {
d=m_image.image.xsize;
value=d; props.set(key, value);
}
if("height"==key) {
d=m_image.image.ysize;
value=d; props.set(key, value);
}
if("fps"==key) {
d=m_fps;
value=d; props.set(key, value);
}
}
}
#endif /* CARBONQUICKTIME */