void qtCanvas::Impl::setupSCComponent() { OSErr err; err = EnterMovies(); CheckError (err, "EnterMovies error" ); mSCComponent = OpenDefaultComponent( StandardCompressionType, StandardCompressionSubType); CheckMoviesError("OpenDefaultComponent"); if (sSCSettings) { SCSetInfo(mSCComponent, scSettingsStateType, &sSCSettings); } else { SCSpatialSettings spatial; SCTemporalSettings temporal; long preference; CodecFlags codecFlags; spatial.codecType = kAnimationCodecType; spatial.codec = NULL; spatial.depth = 32; // reset when the preview is set up spatial.spatialQuality = codecNormalQuality; temporal.temporalQuality = codecNormalQuality; temporal.frameRate = FloatToFixed(15.0); temporal.keyFrameRate = FixedToInt(temporal.frameRate) * 2; preference = scListEveryCodec; //preference |= scShowBestDepth; //preference |= scUseMovableModal; codecFlags = codecFlagUpdatePreviousComp; SCSetInfo(mSCComponent, scSpatialSettingsType, &spatial); SCSetInfo(mSCComponent, scTemporalSettingsType, &temporal); SCSetInfo(mSCComponent, scPreferenceFlagsType, &preference); SCSetInfo(mSCComponent, scCodecFlagsType, &codecFlags); } }
static PyObject *Cm_OpenDefaultComponent(PyObject *_self, PyObject *_args) { PyObject *_res = NULL; ComponentInstance _rv; OSType componentType; OSType componentSubType; #ifndef OpenDefaultComponent PyMac_PRECHECK(OpenDefaultComponent); #endif if (!PyArg_ParseTuple(_args, "O&O&", PyMac_GetOSType, &componentType, PyMac_GetOSType, &componentSubType)) return NULL; _rv = OpenDefaultComponent(componentType, componentSubType); _res = Py_BuildValue("O&", CmpInstObj_New, _rv); return _res; }
/* LowRunAppleScript compiles and runs an AppleScript provided as text in the buffer pointed to by text. textLength bytes will be compiled from this buffer and run as an AppleScript using all of the default environment and execution settings. resultData must be non-NULL, and should have been previously initialised, for example with _hs_initNull. The result returned by the execution command will be returned as typeUTF8Text in this descriptor record (or typeNull if there is no result information). If the function returns errOSAScriptError, then resultData will be set to a descriptive error message describing the error (if one is available). */ OSStatus LowRunAppleScript(const void* text, long textLength, AEDesc *resultData) { ComponentInstance theComponent; AEDesc scriptTextDesc; OSStatus err; OSAID scriptID, resultID; /* set up locals to a known state */ theComponent = NULL; AECreateDesc(typeNull, NULL, 0, &scriptTextDesc); scriptID = kOSANullScript; resultID = kOSANullScript; /* open the scripting component */ theComponent = OpenDefaultComponent(kOSAComponentType, typeAppleScript); if (theComponent == NULL) { err = paramErr; goto bail; } /* put the script text into an aedesc */ err = AECreateDesc(typeUTF8Text, text, textLength, &scriptTextDesc); if (err != noErr) goto bail; /* compile the script */ err = OSACompile(theComponent, &scriptTextDesc, kOSAModeNull, &scriptID); if (err != noErr) goto bail; /* run the script/get the result */ err = OSAExecute(theComponent, scriptID, kOSANullScript, kOSAModeNull, &resultID); if (resultData != NULL) { if (err == noErr && resultID != kOSANullScript) { OSADisplay(theComponent, resultID, typeUTF8Text, kOSAModeNull, resultData); } } bail: if (err == errOSAScriptError) { AECreateDesc(typeNull, NULL, 0, resultData); OSAScriptError(theComponent, kOSAErrorMessage, typeUTF8Text, resultData); } AEDisposeDesc(&scriptTextDesc); if (scriptID != kOSANullScript) OSADispose(theComponent, scriptID); if (resultID != kOSANullScript) OSADispose(theComponent, resultID); if (theComponent != NULL) CloseComponent(theComponent); return err; }
static PyObject *AE_GetSysTerminology(PyObject* self, PyObject* args) { OSType componentSubType; ComponentInstance component; AEDesc theDesc; OSAError err; if (!PyArg_ParseTuple(args, "O&", AE_GetOSType, &componentSubType)) return NULL; component = OpenDefaultComponent(kOSAComponentType, componentSubType); err = GetComponentInstanceError(component); if (err) return AE_MacOSError(err); err = OSAGetSysTerminology(component, kOSAModeNull, 0, &theDesc); CloseComponent(component); if (err) return AE_MacOSError(err); return BuildTerminologyList(&theDesc, typeAEUT); }
static PyObject * PyOSA_GetSysTerminology(PyObject* self, PyObject* args) { AEDesc theDesc = {0,0}; ComponentInstance defaultComponent = NULL; SInt16 defaultTerminology = 0; OSAError err; /* Accept any args for sake of backwards compatibility, then ignore them. */ defaultComponent = OpenDefaultComponent (kOSAComponentType, 'ascr'); err = GetComponentInstanceError (defaultComponent); if (err) return PyMac_Error(err); err = OSAGetSysTerminology ( defaultComponent, kOSAModeNull, defaultTerminology, &theDesc ); if (err) return PyMac_Error(err); return Py_BuildValue("O&", AEDesc_New, &theDesc); }
//============================================================================= // QutTexture_CreateCompressedTextureObjectFromPixmap : Create a QD3D // texture. //----------------------------------------------------------------------------- TQ3TextureObject QutTexture_CreateCompressedTextureObjectFromPixmap( PixMapHandle sourcePixmap, TQ3PixelType pixelType, TQ3Boolean wantMipMaps ) { ComponentInstance theCompressor = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType ) ; Rect bounds = (** sourcePixmap).bounds; TQ3TextureObject compressedTexture = NULL; TQ3Status qd3dStatus = kQ3Success; TQ3CompressedPixmap compressedPixmap; // set the fields I must compressedPixmap.imageDescByteOrder = kQ3EndianBig; compressedPixmap.makeMipmaps = wantMipMaps; compressedPixmap.width = bounds.right - bounds.left; compressedPixmap.height = bounds.top - bounds.bottom; compressedPixmap.pixelSize = 32; compressedPixmap.pixelType = pixelType ; // use QD3D for the hard work, use the minimim quality to see the // results of compression qd3dStatus = Q3CompressedPixmapTexture_CompressImage( &compressedPixmap, sourcePixmap, compressorComponentType, bestCompressionCodec, 0, codecMinQuality); if( qd3dStatus == kQ3Success ) compressedTexture = Q3CompressedPixmapTexture_New( &compressedPixmap ) ; return(compressedTexture); }
int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports) { OSErr err = noErr; char name[2048]; char theFullPath[255]; #ifdef __APPLE__ int myFile; FSRef myRef; #else char *qtname; #endif int success= 1; if(qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); if(qtdata) { if(qtdata->theComponent) CloseComponent(qtdata->theComponent); free_qtcomponentdata(); } qtdata = MEM_callocN(sizeof(QuicktimeComponentData), "QuicktimeCodecDataExt"); if(rd->qtcodecdata == NULL || rd->qtcodecdata->cdParms == NULL) { get_qtcodec_settings(rd, reports); } else { qtdata->theComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); QT_GetCodecSettingsFromScene(rd, reports); check_renderbutton_framerate(rd, reports); } sframe = (rd->sfra); filepath_qt(name, rd); #ifdef __APPLE__ EnterMoviesOnThread(0); sprintf(theFullPath, "%s", name); /* hack: create an empty file to make FSPathMakeRef() happy */ myFile = open(theFullPath, O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRUSR|S_IWUSR); if (myFile < 0) { BKE_reportf(reports, RPT_ERROR, "error while creating movie file!\n"); /* do something? */ } close(myFile); err = FSPathMakeRef((const UInt8 *)theFullPath, &myRef, 0); CheckError(err, "FsPathMakeRef error", reports); err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &qtexport->theSpec, NULL); CheckError(err, "FsGetCatalogInfoRef error", reports); #endif #ifdef _WIN32 qtname = get_valid_qtname(name); sprintf(theFullPath, "%s", qtname); strcpy(name, qtname); MEM_freeN(qtname); CopyCStringToPascal(theFullPath, qtexport->qtfilename); err = FSMakeFSSpec(0, 0L, qtexport->qtfilename, &qtexport->theSpec); #endif err = CreateMovieFile (&qtexport->theSpec, kMyCreatorType, smCurrentScript, createMovieFileDeleteCurFile | createMovieFileDontCreateResFile, &qtexport->resRefNum, &qtexport->theMovie ); CheckError(err, "CreateMovieFile error", reports); if(err != noErr) { BKE_reportf(reports, RPT_ERROR, "Unable to create Quicktime movie: %s", name); success= 0; #ifdef __APPLE__ ExitMoviesOnThread(); #endif } else { //printf("Created QuickTime movie: %s\n", name); QT_CreateMyVideoTrack(rectx, recty, reports); } return success; }
bool wxOSXQuickTimeSoundData::Play(unsigned flags) { if ( m_movie ) Stop(); m_flags = flags; if (!wxInitQT()) return false; if( m_soundHandle ) { Handle dataRef = nil; MovieImportComponent miComponent; Track targetTrack = nil; TimeValue addedDuration = 0; long outFlags = 0; OSErr err; ComponentResult result; err = PtrToHand(&m_soundHandle, &dataRef, sizeof(Handle)); HLock(m_soundHandle); if (memcmp(&(*m_soundHandle)[8], "WAVE", 4) == 0) miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeWave); else if (memcmp(&(*m_soundHandle)[8], "AIFF", 4) == 0) miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFF); else if (memcmp(&(*m_soundHandle)[8], "AIFC", 4) == 0) miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFC); else { HUnlock(m_soundHandle); wxLogSysError(wxT("wxSound - Location in memory does not contain valid data")); return false; } HUnlock(m_soundHandle); m_movie = NewMovie(0); result = MovieImportDataRef(miComponent, dataRef, HandleDataHandlerSubType, m_movie, nil, &targetTrack, nil, &addedDuration, movieImportCreateTrack, &outFlags); if (result != noErr) { wxLogSysError(wxString::Format(wxT("Couldn't import movie data\nError:%i"), (int)result)); } SetMovieVolume(m_movie, kFullVolume); GoToBeginningOfMovie(m_movie); } else { OSErr err = noErr ; Handle dataRef = NULL; OSType dataRefType; err = QTNewDataReferenceFromFullPathCFString(wxCFStringRef(m_sndname,wxLocale::GetSystemEncoding()), (UInt32)kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType); wxASSERT(err == noErr); if (NULL != dataRef || err != noErr) { err = NewMovieFromDataRef( &m_movie, newMovieDontAskUnresolvedDataRefs , NULL, dataRef, dataRefType ); wxASSERT(err == noErr); DisposeHandle(dataRef); } if (err != noErr) { wxLogSysError( wxString::Format(wxT("wxSound - Could not open file: %s\nError:%i"), m_sndname.c_str(), err ) ); return false; } } //Start the m_movie! StartMovie(m_movie); if (flags & wxSOUND_ASYNC) { CreateAndStartTimer(); } else { wxASSERT_MSG(!(flags & wxSOUND_LOOP), wxT("Can't loop and play syncronously at the same time")); //Play movie until it ends, then exit //Note that due to quicktime caching this may not always //work 100% correctly while (!IsMovieDone(m_movie)) MoviesTask(m_movie, 1); DoStop(); } return true; }
static gboolean gst_osx_video_src_start (GstBaseSrc * src) { GstOSXVideoSrc *self; GObjectClass *gobject_class; GstOSXVideoSrcClass *klass; ComponentResult err; self = GST_OSX_VIDEO_SRC (src); gobject_class = G_OBJECT_GET_CLASS (src); klass = GST_OSX_VIDEO_SRC_CLASS (gobject_class); GST_DEBUG_OBJECT (src, "entering"); if (!klass->movies_enabled) return FALSE; self->seq_num = 0; self->seq_grab = OpenDefaultComponent (SeqGrabComponentType, 0); if (self->seq_grab == NULL) { err = paramErr; GST_ERROR_OBJECT (self, "OpenDefaultComponent failed. paramErr=%d", (int) err); goto fail; } err = SGInitialize (self->seq_grab); if (err != noErr) { GST_ERROR_OBJECT (self, "SGInitialize returned %d", (int) err); goto fail; } err = SGSetDataRef (self->seq_grab, 0, 0, seqGrabDontMakeMovie); if (err != noErr) { GST_ERROR_OBJECT (self, "SGSetDataRef returned %d", (int) err); goto fail; } err = SGNewChannel (self->seq_grab, VideoMediaType, &self->video_chan); if (err != noErr) { GST_ERROR_OBJECT (self, "SGNewChannel returned %d", (int) err); goto fail; } if (!device_select (self)) goto fail; GST_DEBUG_OBJECT (self, "started"); return TRUE; fail: self->video_chan = NULL; if (self->seq_grab) { err = CloseComponent (self->seq_grab); if (err != noErr) GST_WARNING_OBJECT (self, "CloseComponent returned %d", (int) err); self->seq_grab = NULL; } return FALSE; }
/* return a list of available devices. the default device (if any) will be * the first in the list. */ static GList * device_list (GstOSXVideoSrc * src) { SeqGrabComponent component = NULL; SGChannel channel; SGDeviceList deviceList; SGDeviceName *deviceEntry; SGDeviceInputList inputList; SGDeviceInputName *inputEntry; ComponentResult err; int n, i; GList *list; video_device *dev, *default_dev; gchar sgname[256]; gchar friendly_name[256]; list = NULL; default_dev = NULL; if (src->video_chan) { /* if we already have a video channel allocated, use that */ GST_DEBUG_OBJECT (src, "reusing existing channel for device_list"); channel = src->video_chan; } else { /* otherwise, allocate a temporary one */ component = OpenDefaultComponent (SeqGrabComponentType, 0); if (!component) { err = paramErr; GST_ERROR_OBJECT (src, "OpenDefaultComponent failed. paramErr=%d", (int) err); goto end; } err = SGInitialize (component); if (err != noErr) { GST_ERROR_OBJECT (src, "SGInitialize returned %d", (int) err); goto end; } err = SGSetDataRef (component, 0, 0, seqGrabDontMakeMovie); if (err != noErr) { GST_ERROR_OBJECT (src, "SGSetDataRef returned %d", (int) err); goto end; } err = SGNewChannel (component, VideoMediaType, &channel); if (err != noErr) { GST_ERROR_OBJECT (src, "SGNewChannel returned %d", (int) err); goto end; } } err = SGGetChannelDeviceList (channel, sgDeviceListIncludeInputs, &deviceList); if (err != noErr) { GST_ERROR_OBJECT (src, "SGGetChannelDeviceList returned %d", (int) err); goto end; } for (n = 0; n < (*deviceList)->count; ++n) { deviceEntry = &(*deviceList)->entry[n]; if (deviceEntry->flags & sgDeviceNameFlagDeviceUnavailable) continue; p2cstrcpy (sgname, deviceEntry->name); inputList = deviceEntry->inputs; if (inputList && (*inputList)->count >= 1) { for (i = 0; i < (*inputList)->count; ++i) { inputEntry = &(*inputList)->entry[i]; p2cstrcpy (friendly_name, inputEntry->name); dev = video_device_alloc (); dev->id = create_device_id (sgname, i); if (!dev->id) { video_device_free (dev); i = -1; break; } dev->name = g_strdup (friendly_name); list = g_list_append (list, dev); /* if this is the default device, note it */ if (n == (*deviceList)->selectedIndex && i == (*inputList)->selectedIndex) { default_dev = dev; } } /* error */ if (i == -1) break; } else { /* ### can a device have no defined inputs? */ dev = video_device_alloc (); dev->id = create_device_id (sgname, -1); if (!dev->id) { video_device_free (dev); break; } dev->name = g_strdup (sgname); list = g_list_append (list, dev); /* if this is the default device, note it */ if (n == (*deviceList)->selectedIndex) { default_dev = dev; } } } /* move default device to the front */ if (default_dev) { list = g_list_remove (list, default_dev); list = g_list_prepend (list, default_dev); } end: if (!src->video_chan && component) { err = CloseComponent (component); if (err != noErr) GST_WARNING_OBJECT (src, "CloseComponent returned %d", (int) err); } return list; }
static int sequence_grabber_start(V4lState *s) { int err; Rect theRect = {0, 0, s->vsize.height, s->vsize.width}; err = QTNewGWorld(&(s->pgworld), // returned GWorld k24BGRPixelFormat, &theRect, // bounding rectangle 0, // color table NULL, // graphic device handle 0); // flags if (err!=noErr) { return -1; } if(!LockPixels(GetPortPixMap(s->pgworld))) { v4m_close(s); return -1; } s->seqgrab = OpenDefaultComponent(SeqGrabComponentType, 0); err = SGInitialize(s->seqgrab); if (err!=noErr) { v4m_close(s); return -1; } err = SGSetDataRef(s->seqgrab, 0, 0, seqGrabDontMakeMovie); if (err!=noErr) { v4m_close(s); return -1; } err = SGSetGWorld(s->seqgrab, s->pgworld, GetMainDevice()); if (err!=noErr) { v4m_close(s); return -1; } err = SGNewChannel(s->seqgrab, VideoMediaType, &s->sgchanvideo); if (err!=noErr) { v4m_close(s); return -1; } err = SGSetChannelBounds(s->sgchanvideo, &theRect); if (err!=noErr) { v4m_close(s); return -1; } err = SGSetChannelUsage(s->sgchanvideo, seqGrabRecord); if (err!=noErr) { v4m_close(s); return -1; } err = SGSetDataProc(s->seqgrab,NewSGDataUPP(sgdata_callback),(long)s); if (err!=noErr) { v4m_close(s); return -1; } err = SGStartRecord(s->seqgrab); if (err!=noErr) { v4m_close(s); return -1; } return 0; }
void QTVectors_CreateVectorMovie (UInt32 theBuildAtomMethod) { Handle myHandle = NULL; ImageDescriptionHandle mySampleDesc = NULL; short myResRefNum = 0; short myResID = movieInDataForkResID; Movie myMovie = NULL; Track myTrack; Media myMedia; FSSpec myFile; Boolean myIsSelected = false; Boolean myIsReplacing = false; StringPtr myPrompt = QTUtils_ConvertCToPascalString(kVectorSavePrompt); StringPtr myFileName = QTUtils_ConvertCToPascalString(kVectorSaveMovieFileName); ComponentInstance myComponent; ComponentResult myResult; long myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile; OSErr myErr = noErr; // METHOD ONE: use a raw data stream if (theBuildAtomMethod == kUseRawDataStream) { // kUseRawDataStream: build the vector data using a stream of hard-coded raw data // NOTE: the data in the stream *must* be big-endian, since it's stored in a QuickTime atom container. long myPath[] = { EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurveAntialiasControlAtom), EndianU32_NtoB(kCurveAntialiasOn), EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurveFillTypeAtom), EndianU32_NtoB(gxEvenOddFill), // a big white enclosing rectangle (600 x 600) EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(ARGBColor)), EndianU32_NtoB(kCurveARGBColorAtom), EndianU32_NtoB(0xffffffff), // alpha, red EndianU32_NtoB(0xffffffff), // green, blue // it's white! EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)*11), EndianU32_NtoB(kCurvePathAtom), EndianU32_NtoB(1), // one contour in path EndianU32_NtoB(4), // four points in path EndianU32_NtoB(0x00000000), // all points are on the curve: it's a rectangle! EndianU32_NtoB(0x00000000), EndianU32_NtoB(0x00000000), // top left EndianU32_NtoB(0x02580000), EndianU32_NtoB(0x00000000), // top right EndianU32_NtoB(0x02580000), EndianU32_NtoB(0x02580000), // bottom right EndianU32_NtoB(0x00000000), EndianU32_NtoB(0x02580000), // bottom left // a black rounded square, centered at 150,150 EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(ARGBColor)), EndianU32_NtoB(kCurveARGBColorAtom), EndianU32_NtoB(0x00000000), // alpha, red EndianU32_NtoB(0x00000000), // green, blue // it's black! EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)*11), EndianU32_NtoB(kCurvePathAtom), EndianU32_NtoB(1), // one contour in path EndianU32_NtoB(4), // four points in path EndianU32_NtoB(0xffffffff), // all points are off the curve: it's a rounded square! EndianU32_NtoB(0x00640000), EndianU32_NtoB(0x00640000), EndianU32_NtoB(0x00C80000), EndianU32_NtoB(0x00640000), EndianU32_NtoB(0x00C80000), EndianU32_NtoB(0x00C80000), EndianU32_NtoB(0x00640000), EndianU32_NtoB(0x00C80000), EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurveFillTypeAtom), EndianU32_NtoB(gxEvenOddFill), EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurvePenThicknessAtom), EndianU32_NtoB(0x100000), // enable linear gradient for all following atoms EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurveGradientTypeAtom), EndianU32_NtoB(kLinearGradient), // define the gradient: red -> green -> red -> blue EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(GradientColorRecord)*4), EndianU32_NtoB(kCurveGradientRecordAtom), EndianU32_NtoB(0xffffffff), // gradient color record 1: EndianU32_NtoB(0x00000000), // red EndianU32_NtoB(0x00000000), // beginning of gradient EndianU32_NtoB(0x77770000), // gradient color record 2: EndianU32_NtoB(0xffff0000), // green EndianU32_NtoB(0x00004000), EndianU32_NtoB(0x3333ffff), // gradient color record 3: EndianU32_NtoB(0x00000000), // red EndianU32_NtoB(0x0000C000), EndianU32_NtoB(0xffff0000), // gradient color record 4: EndianU32_NtoB(0x0000ffff), // blue EndianU32_NtoB(0x00010000), // end of gradient EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)), EndianU32_NtoB(kCurveGradientAngleAtom), EndianU32_NtoB(0x00450000), // gradient at 45û angle // a green rectangle, centered at 40,40, painted with a linear gradient EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(ARGBColor)), EndianU32_NtoB(kCurveARGBColorAtom), EndianU32_NtoB(0x00000000), // alpha, red EndianU32_NtoB(0xffff0000), // green, blue // it's green! EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)*11), EndianU32_NtoB(kCurvePathAtom), EndianU32_NtoB(1), // one contour in path EndianU32_NtoB(4), // four points in path EndianU32_NtoB(0x00000000), // all points are on the curve: it's a rectangle! EndianU32_NtoB(0x00100000), EndianU32_NtoB(0x00100000), EndianU32_NtoB(0x00400000), EndianU32_NtoB(0x00100000), EndianU32_NtoB(0x00400000), EndianU32_NtoB(0x00400000), EndianU32_NtoB(0x00100000), EndianU32_NtoB(0x00400000), // disable gradient for all following atoms (since no atom data) EndianU32_NtoB(kSizeOfSizeAndTagFields), EndianU32_NtoB(kCurveGradientRecordAtom), // a red rounded square, centered at 50,50 EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(ARGBColor)), EndianU32_NtoB(kCurveARGBColorAtom), EndianU32_NtoB(0x3333ffff), // alpha, red EndianU32_NtoB(0x00000000), // green, blue // it's red! EndianU32_NtoB(kSizeOfSizeAndTagFields + sizeof(long)*11), EndianU32_NtoB(kCurvePathAtom), EndianU32_NtoB(1L), // one contour in path EndianU32_NtoB(4L), // four points in path EndianU32_NtoB(0xffffffff), // all points are off the curve: it's a rounded square! EndianU32_NtoB(0x001e0000), EndianU32_NtoB(0x001e0000), EndianU32_NtoB(0x00460000), EndianU32_NtoB(0x001e0000), EndianU32_NtoB(0x00460000), EndianU32_NtoB(0x00460000), EndianU32_NtoB(0x001e0000), EndianU32_NtoB(0x00460000), EndianU32_NtoB(kSizeOfZeroAtomHeader), EndianU32_NtoB(kCurveEndAtom), }; myHandle = NewHandle(sizeof(myPath)); if (myHandle == NULL) goto bail; BlockMove(myPath, *myHandle, sizeof(myPath)); } // end of kUseRawDataStream // METHOD TWO: use the Curve Utilities API if (theBuildAtomMethod == kUseCurveUtilities) { // kUseCurveUtilities: build the vector data using the Curve Utilities API Handle myPath; gxPoint myPoint; long myAtomData[14]; ARGBColor myColor; GradientColorRecord myGradients[4]; // open the vector codec; we'll need it for some subsequent calls myComponent = OpenDefaultComponent(decompressorComponentType, kVectorCodecType); if (myComponent == NULL) goto bail; // create a new, empty vector data stream myResult = CurveCreateVectorStream(myComponent, &myHandle); if (myResult != noErr) goto bail; // now start adding atoms holding the vector data // set antialiasing on myAtomData[0] = EndianU32_NtoB(kCurveAntialiasOn); CurveAddAtomToVectorStream(myComponent, kCurveAntialiasControlAtom, sizeof(long), myAtomData, myHandle); // set fill type myAtomData[0] = EndianU32_NtoB(gxEvenOddFill); CurveAddAtomToVectorStream(myComponent, kCurveFillTypeAtom, sizeof(long), myAtomData, myHandle); // a big white enclosing rectangle (600 x 600) myColor.alpha = EndianU16_NtoB(0xffff); myColor.red = EndianU16_NtoB(0xffff); myColor.green = EndianU16_NtoB(0xffff); myColor.blue = EndianU16_NtoB(0xffff); CurveAddAtomToVectorStream(myComponent, kCurveARGBColorAtom, sizeof(ARGBColor), &myColor, myHandle); #if USE_CURVE_INSERT_POINT_INTO_PATH // create a new, empty path CurveNewPath(myComponent, &myPath); myPoint.x = 0x00000000; myPoint.y = 0x00000000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 0, true); myPoint.x = 0x02580000; myPoint.y = 0x00000000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 1, true); myPoint.x = 0x02580000; myPoint.y = 0x02580000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 2, true); myPoint.x = 0x00000000; myPoint.y = 0x02580000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 3, true); // add the 'path' atom to the vector data stream CurveAddPathAtomToVectorStream(myComponent, myPath, myHandle); DisposeHandle(myPath); #else myAtomData[0] = EndianU32_NtoB(1L); myAtomData[1] = EndianU32_NtoB(4L); myAtomData[2] = EndianU32_NtoB(0x00000000); myAtomData[3] = EndianU32_NtoB(0x00000000); myAtomData[4] = EndianU32_NtoB(0x00000000); myAtomData[5] = EndianU32_NtoB(0x02580000); myAtomData[6] = EndianU32_NtoB(0x00000000); myAtomData[7] = EndianU32_NtoB(0x02580000); myAtomData[8] = EndianU32_NtoB(0x02580000); myAtomData[9] = EndianU32_NtoB(0x00000000); myAtomData[10] = EndianU32_NtoB(0x02580000); CurveAddAtomToVectorStream(myComponent, kCurvePathAtom, sizeof(long)*11, myAtomData, myHandle); #endif // a black rounded square, centered at 150,150 myColor.alpha = EndianU16_NtoB(0x0000); myColor.red = EndianU16_NtoB(0x0000); myColor.green = EndianU16_NtoB(0x0000); myColor.blue = EndianU16_NtoB(0x0000); CurveAddAtomToVectorStream(myComponent, kCurveARGBColorAtom, sizeof(ARGBColor), &myColor, myHandle); #if USE_CURVE_INSERT_POINT_INTO_PATH // create a new, empty path CurveNewPath(myComponent, &myPath); myPoint.x = 0x00640000; myPoint.y = 0x00640000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 0, false); myPoint.x = 0x00C80000; myPoint.y = 0x00640000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 1, false); myPoint.x = 0x00C80000; myPoint.y = 0x00C80000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 2, false); myPoint.x = 0x00640000; myPoint.y = 0x00C80000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 3, false); // add the 'path' atom to the vector data stream CurveAddPathAtomToVectorStream(myComponent, myPath, myHandle); DisposeHandle(myPath); #else myAtomData[0] = EndianU32_NtoB(1L); myAtomData[1] = EndianU32_NtoB(4L); myAtomData[2] = EndianU32_NtoB(0xffffffff); myAtomData[3] = EndianU32_NtoB(0x00640000); myAtomData[4] = EndianU32_NtoB(0x00640000); myAtomData[5] = EndianU32_NtoB(0x00C80000); myAtomData[6] = EndianU32_NtoB(0x00640000); myAtomData[7] = EndianU32_NtoB(0x00C80000); myAtomData[8] = EndianU32_NtoB(0x00C80000); myAtomData[9] = EndianU32_NtoB(0x00640000); myAtomData[10] = EndianU32_NtoB(0x00C80000); CurveAddAtomToVectorStream(myComponent, kCurvePathAtom, sizeof(long)*11, myAtomData, myHandle); #endif // set fill type myAtomData[0] = EndianU32_NtoB(gxEvenOddFill); CurveAddAtomToVectorStream(myComponent, kCurveFillTypeAtom, sizeof(long), myAtomData, myHandle); // set pen thickness myAtomData[0] = EndianU32_NtoB(0x100000); CurveAddAtomToVectorStream(myComponent, kCurvePenThicknessAtom, sizeof(long), myAtomData, myHandle); // enable linear gradient for all following atoms myAtomData[0] = EndianU32_NtoB(kLinearGradient); CurveAddAtomToVectorStream(myComponent, kCurveGradientTypeAtom, sizeof(long), myAtomData, myHandle); // define the gradient: red -> green -> red -> blue myGradients[0].thisColor.alpha = EndianU16_NtoB(0xffff); myGradients[0].thisColor.red = EndianU16_NtoB(0xffff); myGradients[0].thisColor.green = EndianU16_NtoB(0x0000); myGradients[0].thisColor.blue = EndianU16_NtoB(0x0000); myGradients[0].endingPercentage = EndianU32_NtoB(0x00000000); myGradients[1].thisColor.alpha = EndianU16_NtoB(0x7777); myGradients[1].thisColor.red = EndianU16_NtoB(0x0000); myGradients[1].thisColor.green = EndianU16_NtoB(0xffff); myGradients[1].thisColor.blue = EndianU16_NtoB(0x0000); myGradients[1].endingPercentage = EndianU32_NtoB(0x00004000); myGradients[2].thisColor.alpha = EndianU16_NtoB(0x3333); myGradients[2].thisColor.red = EndianU16_NtoB(0xffff); myGradients[2].thisColor.green = EndianU16_NtoB(0x0000); myGradients[2].thisColor.blue = EndianU16_NtoB(0x0000); myGradients[2].endingPercentage = EndianU32_NtoB(0x0000C000); myGradients[3].thisColor.alpha = EndianU16_NtoB(0xffff); myGradients[3].thisColor.red = EndianU16_NtoB(0x0000); myGradients[3].thisColor.green = EndianU16_NtoB(0x0000); myGradients[3].thisColor.blue = EndianU16_NtoB(0xffff); myGradients[3].endingPercentage = EndianU32_NtoB(0x00010000); CurveAddAtomToVectorStream(myComponent, kCurveGradientRecordAtom, sizeof(GradientColorRecord)*4, myGradients, myHandle); // set gradient angle myAtomData[0] = EndianU32_NtoB(0x00450000); CurveAddAtomToVectorStream(myComponent, kCurveGradientAngleAtom, sizeof(long), myAtomData, myHandle); // a green rectangle, centered at 40,40, painted with a linear gradient myColor.alpha = EndianU16_NtoB(0x0000); myColor.red = EndianU16_NtoB(0x0000); myColor.green = EndianU16_NtoB(0xffff); myColor.blue = EndianU16_NtoB(0x0000); CurveAddAtomToVectorStream(myComponent, kCurveARGBColorAtom, sizeof(ARGBColor), &myColor, myHandle); #if USE_CURVE_INSERT_POINT_INTO_PATH // create a new, empty path CurveNewPath(myComponent, &myPath); myPoint.x = 0x00100000; myPoint.y = 0x00100000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 0, true); myPoint.x = 0x00400000; myPoint.y = 0x00100000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 1, true); myPoint.x = 0x00400000; myPoint.y = 0x00400000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 2, true); myPoint.x = 0x00100000; myPoint.y = 0x00400000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 3, true); // add the 'path' atom to the vector data stream CurveAddPathAtomToVectorStream(myComponent, myPath, myHandle); DisposeHandle(myPath); #else myAtomData[0] = EndianU32_NtoB(1L); myAtomData[1] = EndianU32_NtoB(4L); myAtomData[2] = EndianU32_NtoB(0x00000000); myAtomData[3] = EndianU32_NtoB(0x00100000); myAtomData[4] = EndianU32_NtoB(0x00100000); myAtomData[5] = EndianU32_NtoB(0x00400000); myAtomData[6] = EndianU32_NtoB(0x00100000); myAtomData[7] = EndianU32_NtoB(0x00400000); myAtomData[8] = EndianU32_NtoB(0x00400000); myAtomData[9] = EndianU32_NtoB(0x00100000); myAtomData[10] = EndianU32_NtoB(0x00400000); CurveAddAtomToVectorStream(myComponent, kCurvePathAtom, sizeof(long)*11, myAtomData, myHandle); #endif // disable gradient for all following atoms (since no atom data) CurveAddAtomToVectorStream(myComponent, kCurveGradientTypeAtom, 0, NULL, myHandle); // a red rounded square, centered at 50,50 myColor.alpha = EndianU16_NtoB(0x3333); myColor.red = EndianU16_NtoB(0xffff); myColor.green = EndianU16_NtoB(0x0000); myColor.blue = EndianU16_NtoB(0x0000); CurveAddAtomToVectorStream(myComponent, kCurveARGBColorAtom, sizeof(ARGBColor), &myColor, myHandle); #if USE_CURVE_INSERT_POINT_INTO_PATH // create a new, empty path CurveNewPath(myComponent, &myPath); myPoint.x = 0x001e0000; myPoint.y = 0x001e0000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 0, false); myPoint.x = 0x00460000; myPoint.y = 0x001e0000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 1, false); myPoint.x = 0x00460000; myPoint.y = 0x00460000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 2, false); myPoint.x = 0x001e0000; myPoint.y = 0x00460000; CurveInsertPointIntoPath(myComponent, &myPoint, myPath, 0, 3, false); // add the 'path' atom to the vector data stream CurveAddPathAtomToVectorStream(myComponent, myPath, myHandle); DisposeHandle(myPath); #else myAtomData[0] = EndianU32_NtoB(1L); myAtomData[1] = EndianU32_NtoB(4L); myAtomData[2] = EndianU32_NtoB(0xffffffff); myAtomData[3] = EndianU32_NtoB(0x001e0000); myAtomData[4] = EndianU32_NtoB(0x001e0000); myAtomData[5] = EndianU32_NtoB(0x00460000); myAtomData[6] = EndianU32_NtoB(0x001e0000); myAtomData[7] = EndianU32_NtoB(0x00460000); myAtomData[8] = EndianU32_NtoB(0x00460000); myAtomData[9] = EndianU32_NtoB(0x001e0000); myAtomData[10] = EndianU32_NtoB(0x00460000); CurveAddAtomToVectorStream(myComponent, kCurvePathAtom, sizeof(long)*11, myAtomData, myHandle); #endif // add the 'zero' atom to the vector data stream CurveAddZeroAtomToVectorStream(myComponent, myHandle); } // end of kUseCurveUtilities // create the image description mySampleDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription)); if (mySampleDesc == NULL) goto bail; // fill in the fields of the image description (**mySampleDesc).idSize = sizeof(ImageDescription); (**mySampleDesc).cType = kVectorCodecType; (**mySampleDesc).vendor = kAppleManufacturer; (**mySampleDesc).temporalQuality = codecNormalQuality; (**mySampleDesc).spatialQuality = codecNormalQuality; (**mySampleDesc).width = 300; (**mySampleDesc).height = 300; (**mySampleDesc).hRes = 72L << 16; (**mySampleDesc).vRes = 72L << 16; (**mySampleDesc).dataSize = 0L; (**mySampleDesc).frameCount = 1; (**mySampleDesc).depth = 0; (**mySampleDesc).clutID = -1; // prompt user for new file name QTFrame_PutFile(myPrompt, myFileName, &myFile, &myIsSelected, &myIsReplacing); if (!myIsSelected) goto bail; // create a movie file for the destination movie myErr = CreateMovieFile(&myFile, FOUR_CHAR_CODE('TVOD'), smCurrentScript, myFlags, &myResRefNum, &myMovie); if (myErr != noErr) goto bail; // create the vector track and media myTrack = NewMovieTrack(myMovie, FixDiv(300, 1), FixDiv(300, 1), kNoVolume); myMedia = NewTrackMedia(myTrack, VideoMediaType, 600, NULL, 0); // create the vector media sample BeginMediaEdits(myMedia); myErr = AddMediaSample(myMedia, myHandle, 0, GetHandleSize(myHandle), 600, (SampleDescriptionHandle)mySampleDesc, 1, 0, NULL); if (myErr != noErr) goto bail; EndMediaEdits(myMedia); // add the media to the track InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1); AddMovieResource(myMovie, myResRefNum, &myResID, NULL); bail: free(myPrompt); free(myFileName); if (mySampleDesc != NULL) DisposeHandle((Handle)mySampleDesc); if (myResRefNum != 0) CloseMovieFile(myResRefNum); if (myHandle != NULL) DisposeHandle(myHandle); if (myMovie != NULL) DisposeMovie(myMovie); if (myComponent != NULL) CloseComponent(myComponent); }
static int request_qtcodec_settings(bContext *C, wmOperator *op) { OSErr err = noErr; Scene *scene = CTX_data_scene(C); RenderData *rd = &scene->r; // erase any existing codecsetting if(qtdata) { if(qtdata->theComponent) CloseComponent(qtdata->theComponent); free_qtcomponentdata(); } // allocate new qtdata = MEM_callocN(sizeof(QuicktimeComponentData), "QuicktimeComponentData"); qtdata->theComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); // get previous selected codecsetting, from qtatom or detailed settings if(rd->qtcodecdata && rd->qtcodecdata->cdParms) { QT_GetCodecSettingsFromScene(rd, op->reports); } else { SCGetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); SCGetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); SCGetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); qtdata->gSpatialSettings.codecType = rd->qtcodecsettings.codecType; qtdata->gSpatialSettings.codec = (CodecComponent)rd->qtcodecsettings.codec; qtdata->gSpatialSettings.spatialQuality = (rd->qtcodecsettings.codecSpatialQuality * codecLosslessQuality) /100; qtdata->gTemporalSettings.temporalQuality = (rd->qtcodecsettings.codecTemporalQuality * codecLosslessQuality) /100; qtdata->gTemporalSettings.keyFrameRate = rd->qtcodecsettings.keyFrameRate; qtdata->gTemporalSettings.frameRate = ((float)(rd->frs_sec << 16) / rd->frs_sec_base); qtdata->aDataRateSetting.dataRate = rd->qtcodecsettings.bitRate; qtdata->gSpatialSettings.depth = rd->qtcodecsettings.colorDepth; qtdata->aDataRateSetting.minSpatialQuality = (rd->qtcodecsettings.minSpatialQuality * codecLosslessQuality) / 100; qtdata->aDataRateSetting.minTemporalQuality = (rd->qtcodecsettings.minTemporalQuality * codecLosslessQuality) / 100; qtdata->aDataRateSetting.frameDuration = rd->frs_sec; err = SCSetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); CheckError(err, "SCSetInfo1 error", op->reports); err = SCSetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); CheckError(err, "SCSetInfo2 error", op->reports); err = SCSetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); CheckError(err, "SCSetInfo3 error", op->reports); } // put up the dialog box - it needs to be called from the main thread err = SCRequestSequenceSettings(qtdata->theComponent); if (err == scUserCancelled) { return OPERATOR_FINISHED; } // update runtime codecsettings for use with the codec dialog SCGetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); SCGetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); SCGetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); //Fill the render QuicktimeCodecSettings struct rd->qtcodecsettings.codecTemporalQuality = (qtdata->gTemporalSettings.temporalQuality * 100) / codecLosslessQuality; //Do not override scene frame rate (qtdata->gTemporalSettings.framerate) rd->qtcodecsettings.keyFrameRate = qtdata->gTemporalSettings.keyFrameRate; rd->qtcodecsettings.codecType = qtdata->gSpatialSettings.codecType; rd->qtcodecsettings.codec = (int)qtdata->gSpatialSettings.codec; rd->qtcodecsettings.colorDepth = qtdata->gSpatialSettings.depth; rd->qtcodecsettings.codecSpatialQuality = (qtdata->gSpatialSettings.spatialQuality * 100) / codecLosslessQuality; rd->qtcodecsettings.bitRate = qtdata->aDataRateSetting.dataRate; rd->qtcodecsettings.minSpatialQuality = (qtdata->aDataRateSetting.minSpatialQuality * 100) / codecLosslessQuality; rd->qtcodecsettings.minTemporalQuality = (qtdata->aDataRateSetting.minTemporalQuality * 100) / codecLosslessQuality; //Frame duration is already known (qtdata->aDataRateSetting.frameDuration) QT_SaveCodecSettingsToScene(rd, op->reports); // framerate jugglin' if(qtdata->gTemporalSettings.frameRate == 1571553) { // 23.98 fps qtdata->kVideoTimeScale = 24000; qtdata->duration = 1001; rd->frs_sec = 24; rd->frs_sec_base = 1.001; } else if (qtdata->gTemporalSettings.frameRate == 1964113) { // 29.97 fps qtdata->kVideoTimeScale = 30000; qtdata->duration = 1001; rd->frs_sec = 30; rd->frs_sec_base = 1.001; } else if (qtdata->gTemporalSettings.frameRate == 3928227) { // 59.94 fps qtdata->kVideoTimeScale = 60000; qtdata->duration = 1001; rd->frs_sec = 60; rd->frs_sec_base = 1.001; } else { double fps = qtdata->gTemporalSettings.frameRate; qtdata->kVideoTimeScale = 60000; qtdata->duration = qtdata->kVideoTimeScale / (qtdata->gTemporalSettings.frameRate / 65536); if ((qtdata->gTemporalSettings.frameRate & 0xffff) == 0) { rd->frs_sec = fps / 65536; rd->frs_sec_base = 1.0; } else { /* we do our very best... */ rd->frs_sec = fps / 65536; rd->frs_sec_base = 1.0; } } return OPERATOR_FINISHED; }
void QTCmpr_CompressImage (WindowObject theWindowObject) { Rect myRect; GraphicsImportComponent myImporter = NULL; ComponentInstance myComponent = NULL; GWorldPtr myImageWorld = NULL; // the graphics world we draw the image in PixMapHandle myPixMap = NULL; ImageDescriptionHandle myDesc = NULL; Handle myHandle = NULL; OSErr myErr = noErr; if (theWindowObject == NULL) return; ////////// // // get a graphics importer for the image file and determine the natural size of the image; // note that the image file *already* has a graphics importer associated with it (namely // (**theWindowObject).fGraphicsImporter), but we create a new one so that the existing one // can be used to redraw the image in the callback procedure QTCmpr_FilterProc // ////////// myErr = GetGraphicsImporterForFile(&(**theWindowObject).fFileFSSpec, &myImporter); if (myErr != noErr) goto bail; myErr = GraphicsImportGetNaturalBounds(myImporter, &myRect); if (myErr != noErr) goto bail; ////////// // // create an offscreen graphics world and draw the image into it // ////////// myErr = QTNewGWorld(&myImageWorld, 0, &myRect, NULL, NULL, kICMTempThenAppMemory); if (myErr != noErr) goto bail; // get the pixmap of the GWorld; we'll lock the pixmap, just to be safe myPixMap = GetGWorldPixMap(myImageWorld); if (!LockPixels(myPixMap)) goto bail; // set the current port and draw the image GraphicsImportSetGWorld(myImporter, (CGrafPtr)myImageWorld, NULL); GraphicsImportDraw(myImporter); ////////// // // configure and display the standard image compression dialog box // ////////// // open the standard compression dialog component myComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); if (myComponent == NULL) goto bail; // set the picture to be displayed in the dialog box; passing NULL for the rect // means use the entire image; passing 0 for the flags means to use the default // system method of displaying the test image, which is currently a combination // of cropping and scaling; personally, I prefer scaling (your mileage may vary) SCSetTestImagePixMap(myComponent, myPixMap, NULL, scPreferScaling); // install the custom procs, if requested // we can install two kinds of custom procedures for use in connection with // the standard dialog box: (1) a modal-dialog filter function, and (2) a hook // function to handle the custom button in the dialog box if (gUseExtendedProcs) QTCmpr_InstallExtendedProcs(myComponent, (long)myPixMap); // request image compression settings from the user; in other words, put up the dialog box myErr = SCRequestImageSettings(myComponent); if (myErr == scUserCancelled) goto bail; ////////// // // compress the image // ////////// myErr = SCCompressImage(myComponent, myPixMap, NULL, &myDesc, &myHandle); if (myErr != noErr) goto bail; ////////// // // save the compressed image in a new file // ////////// QTCmpr_PromptUserForDiskFileAndSaveCompressed(myHandle, myDesc); bail: if (gUseExtendedProcs) QTCmpr_RemoveExtendedProcs(); if (myPixMap != NULL) if (GetPixelsState(myPixMap) & pixelsLocked) UnlockPixels(myPixMap); if (myImporter != NULL) CloseComponent(myImporter); if (myComponent != NULL) CloseComponent(myComponent); if (myDesc != NULL) DisposeHandle((Handle)myDesc); if (myHandle != NULL) DisposeHandle(myHandle); if (myImageWorld != NULL) DisposeGWorld(myImageWorld); }
bool wxSound::DoPlay(unsigned flags) const { Stop(); Movie movie; switch(m_type) { case wxSound_MEMORY: { if (!wxInitQT()) return false; Handle myHandle, dataRef = nil; MovieImportComponent miComponent; Track targetTrack = nil; TimeValue addedDuration = 0; long outFlags = 0; OSErr err; ComponentResult result; myHandle = NewHandleClear((Size)m_waveLength); BlockMove(m_hSnd, *myHandle, m_waveLength); err = PtrToHand(&myHandle, &dataRef, sizeof(Handle)); if (memcmp(&m_hSnd[8], "WAVE", 4) == 0) miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeWave); else if (memcmp(&m_hSnd[8], "AIFF", 4) == 0) miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFF); else if (memcmp(&m_hSnd[8], "AIFC", 4) == 0) miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFC); else { wxLogSysError(wxT("wxSound - Location in memory does not contain valid data")); return false; } movie = NewMovie(0); result = MovieImportDataRef(miComponent, dataRef, HandleDataHandlerSubType, movie, nil, &targetTrack, nil, &addedDuration, movieImportCreateTrack, &outFlags); if (result != noErr) { wxLogSysError(wxString::Format(wxT("Couldn't import movie data\nError:%i"), (int)result)); } SetMovieVolume(movie, kFullVolume); GoToBeginningOfMovie(movie); DisposeHandle(myHandle); } break; case wxSound_RESOURCE: { SoundComponentData data; unsigned long numframes, offset; ParseSndHeader((SndListHandle)m_hSnd, &data, &numframes, &offset); //m_waveLength = numFrames * data.numChannels; SndChannelPtr pSndChannel; SndNewChannel(&pSndChannel, sampledSynth, initNoInterp + (data.numChannels == 1 ? initMono : initStereo), NULL); if(SndPlay(pSndChannel, (SndListHandle) m_hSnd, flags & wxSOUND_ASYNC ? 1 : 0) != noErr) return false; if (flags & wxSOUND_ASYNC) { lastSoundTimer = ((wxSMTimer*&)m_pTimer) = new wxSMTimer(pSndChannel, m_hSnd, flags & wxSOUND_LOOP ? 1 : 0, &lastSoundIsPlaying); lastSoundIsPlaying = true; ((wxTimer*)m_pTimer)->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS); } else SndDisposeChannel(pSndChannel, TRUE); return true; } break; case wxSound_FILE: { if (!wxInitQT()) return false; OSErr err = noErr ; Handle dataRef = NULL; OSType dataRefType; err = QTNewDataReferenceFromFullPathCFString(wxMacCFStringHolder(m_sndname,wxLocale::GetSystemEncoding()), (UInt32)kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType); wxASSERT(err == noErr); if (NULL != dataRef || err != noErr) { err = NewMovieFromDataRef( &movie, newMovieDontAskUnresolvedDataRefs , NULL, dataRef, dataRefType ); wxASSERT(err == noErr); DisposeHandle(dataRef); } if (err != noErr) { wxLogSysError( wxString::Format(wxT("wxSound - Could not open file: %s\nError:%i"), m_sndname.c_str(), err ) ); return false; } } break; default: return false; }//end switch(m_type) //Start the movie! StartMovie(movie); if (flags & wxSOUND_ASYNC) { //Start timer and play movie asyncronously lastSoundTimer = ((wxQTTimer*&)m_pTimer) = new wxQTTimer(movie, flags & wxSOUND_LOOP ? 1 : 0, &lastSoundIsPlaying); lastSoundIsPlaying = true; ((wxQTTimer*)m_pTimer)->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS); } else { wxASSERT_MSG(!(flags & wxSOUND_LOOP), wxT("Can't loop and play syncronously at the same time")); //Play movie until it ends, then exit //Note that due to quicktime caching this may not always //work 100% correctly while (!IsMovieDone(movie)) MoviesTask(movie, 1); DisposeMovie(movie); } return true; }
OSStatus MovieMaker::setupMovie() { OSStatus error = noErr; FSRef fileRef; FSSpec fileSpec; rowBytes = width * 4; bufferSize = height * rowBytes; buffer = (char*)malloc(bufferSize); invertedBuffer = (char*)malloc(bufferSize); rect.left = 0; rect.top = 0; rect.right = width; rect.bottom = height; error = NewGWorldFromPtr(&gworld, k32ARGBPixelFormat, &rect, 0, 0, 0, buffer, rowBytes); if (error == noErr) { LockPixels(GetGWorldPixMap(gworld)); } // MBW -- I think this needs to happen after all the dialogs, etc. // if (error == noErr) // { // Microseconds(&lastFrameTime); // error = grabFrame(); // } if (error == noErr) { error = EnterMovies(); } if (error == noErr) { ci = OpenDefaultComponent(StandardCompressionType,StandardCompressionSubType); if(ci == NULL) error = paramErr; } if (error == noErr) { long flags; SCGetInfo(ci,scPreferenceFlagsType,&flags); flags &= ~scShowBestDepth; flags |= scAllowZeroFrameRate; SCSetInfo(ci,scPreferenceFlagsType,&flags); } if (error == noErr) { send_agent_pause(); gViewerWindow->mWindow->beforeDialog(); error = SCRequestSequenceSettings(ci); gViewerWindow->mWindow->afterDialog(); send_agent_resume(); if (error == scUserCancelled) { // deal with user cancelling. EndCapture(); } } if (error == noErr) { // This is stoopid. I have to take the passed full path, create the file so I can get an FSRef, and Get Info to get the FSSpec for QuickTime. Could Apple make this any more difficult... FILE* file = LLFile::fopen(fname, "w"); /* Flawfinder: ignore */ if (file) { fclose(file); error = FSPathMakeRef((UInt8*)fname, &fileRef, NULL); if (error == noErr) error = FSGetCatalogInfo(&fileRef, 0, NULL, NULL, &fileSpec, NULL); } else { error = paramErr; } } if (error == noErr) { error = CreateMovieFile(&fileSpec, 'TVOD', smCurrentScript, createMovieFileDeleteCurFile | createMovieFileDontCreateResFile, &movieResRef, &movie); } if (error == noErr) { track = NewMovieTrack(movie, FixRatio(width, 1), FixRatio(height, 1), kNoVolume); error = GetMoviesError(); } if (error == noErr) { media = NewTrackMedia(track, VideoMediaType, 600, NULL, 0); error = GetMoviesError(); } if (error == noErr) { Microseconds(&lastFrameTime); error = grabFrame(); } if (error == noErr) { error = SCCompressSequenceBegin(ci,GetPortPixMap(gworld),nil,&idh); } if (error == noErr) { error = BeginMediaEdits(media); } if (error != noErr) { media = NULL; } return error; }
// ###################################################################### QuickTimeGrabber::Impl::Impl(const Dims& dims) : itsSeqGrab(0, &CloseComponent), itsSGChanVideo(&itsSeqGrab.it), itsDrawSeq(0), itsTimeScale(0), itsTimeBase(0), itsQueuedFrameCount(0), itsSkipFrameCount(0), itsSkipFrameCountTotal(0), itsPrevTime(0), itsFrameCount(0), itsGWorld(0), itsGotFrame(false), itsCurrentImage(), itsErrorMsg(), itsStreamStarted(false) { OSErr err; EnterMovies(); // open the default sequence grabber itsSeqGrab.it = OpenDefaultComponent(SeqGrabComponentType, 0); if (itsSeqGrab.it == NULL) LFATAL("OpenDefaultComponent() failed"); // initialize the default sequence grabber component if (noErr != (err = SGInitialize(itsSeqGrab.it))) LFATAL("SGInitialize() failed (err=%ld)", (long) err); Rect scaleRect; MacSetRect(&scaleRect, 0, 0, dims.w(), dims.h()); ASSERT(itsGWorld == 0); QTNewGWorld(&itsGWorld, k32ARGBPixelFormat, &scaleRect, NULL, NULL, kNativeEndianPixMap); // set its graphics world if (noErr != (err = SGSetGWorld(itsSeqGrab.it, itsGWorld, NULL))) LFATAL("SGSetGWorld() failed (err=%ld)", (long) err); // specify the destination data reference for a record operation // tell it we're not making a movie if the flag seqGrabDontMakeMovie // is used, the sequence grabber still calls your data function, but // does not write any data to the movie file writeType will always // be set to seqGrabWriteAppend if (noErr != (err = SGSetDataRef(itsSeqGrab.it, 0, 0, seqGrabDontMakeMovie | seqGrabDataProcIsInterruptSafe))) LFATAL("SGSetDataRef() failed (err=%ld)", (long) err); Impl::SGChannelHolder sgchanSound(&itsSeqGrab.it); if (noErr != (err = SGNewChannel(itsSeqGrab.it, VideoMediaType, &itsSGChanVideo.it))) LFATAL("SGNewChannel(video) failed (err=%ld)", (long) err); if (noErr != (err = SGNewChannel(itsSeqGrab.it, SoundMediaType, &sgchanSound.it))) { // don't care if we couldn't get a sound channel sgchanSound.it = NULL; LERROR("SGNewChannel(audio) failed (err=%ld)", (long) err); } // get the active rectangle Rect srcBounds; if (noErr != (err = SGGetSrcVideoBounds(itsSGChanVideo.it, &srcBounds))) LFATAL("SGGetSrcVideoBounds() failed (err=%ld)", (long) err); // we always want all the source setVideoChannelBounds(itsSGChanVideo.it, &srcBounds, &srcBounds); // set usage for new video channel to avoid playthrough // note we don't set seqGrabPlayDuringRecord if (noErr != (err = SGSetChannelUsage(itsSGChanVideo.it, seqGrabRecord | seqGrabLowLatencyCapture | seqGrabAlwaysUseTimeBase))) LFATAL("SGSetChannelUsage(video) failed (err=%ld)", (long) err); if (noErr != (err = SGSetChannelUsage(sgchanSound.it, seqGrabRecord | //seqGrabPlayDuringRecord | seqGrabLowLatencyCapture | seqGrabAlwaysUseTimeBase))) LERROR("SGSetChannelUsage(audio) failed (err=%ld)", (long) err); // specify a sequence grabber data function if (noErr != (err = SGSetDataProc(itsSeqGrab.it, NewSGDataUPP(Impl::grabDataProc), (long)(this)))) LFATAL("SGSetDataProc() failed (err=%ld)", (long) err); SGSetChannelRefCon(itsSGChanVideo.it, (long)(this)); // set up the video bottlenecks so we can get our queued frame count VideoBottles vb = { 0 }; if (noErr != (err = SGGetVideoBottlenecks(itsSGChanVideo.it, &vb))) LFATAL("SGGetVideoBottlenecks() failed (err=%ld)", (long) err); vb.procCount = 9; // there are 9 bottleneck procs; this must be filled in vb.grabCompressCompleteProc = NewSGGrabCompressCompleteBottleUPP (Impl::grabCompressCompleteBottle); if (noErr != (err = SGSetVideoBottlenecks(itsSGChanVideo.it, &vb))) LFATAL("SGSetVideoBottlenecks() failed (err=%ld)", (long) err); SGSetFrameRate(itsSGChanVideo.it, FixRatio(30, 1)); }
/* Initialize the QuickTime grabber */ static int qt_open_grabber(struct qt_grabber_state *s, char *fmt) { GrafPtr savedPort; WindowPtr gMonitor; //SGModalFilterUPP seqGrabModalFilterUPP; assert(s != NULL); assert(s->magic == MAGIC_QT_GRABBER); /****************************************************************************************/ /* Step 0: Initialise the QuickTime movie toolbox. */ InitCursor(); EnterMovies(); /****************************************************************************************/ /* Step 1: Create an off-screen graphics world object, into which we can capture video. */ /* Lock it into position, to prevent QuickTime from messing with it while capturing. */ OSType pixelFormat; pixelFormat = FOUR_CHAR_CODE('BGRA'); /****************************************************************************************/ /* Step 2: Open and initialise the default sequence grabber. */ s->grabber = OpenDefaultComponent(SeqGrabComponentType, 0); if (s->grabber == 0) { debug_msg("Unable to open grabber\n"); return 0; } gMonitor = GetDialogWindow(GetNewDialog(1000, NULL, (WindowPtr) - 1L)); GetPort(&savedPort); SetPort((GrafPtr)gMonitor); if (SGInitialize(s->grabber) != noErr) { debug_msg("Unable to init grabber\n"); return 0; } SGSetGWorld(s->grabber, GetDialogPort((DialogPtr)gMonitor), NULL); /****************************************************************************************/ /* Specify the destination data reference for a record operation tell it */ /* we're not making a movie if the flag seqGrabDontMakeMovie is used, */ /* the sequence grabber still calls your data function, but does not */ /* write any data to the movie file writeType will always be set to */ /* seqGrabWriteAppend */ if (SGSetDataRef(s->grabber, 0, 0, seqGrabDontMakeMovie) != noErr) { CloseComponent(s->grabber); debug_msg("Unable to set data ref\n"); return 0; } if (SGSetGWorld(s->grabber, NULL, NULL) != noErr) { debug_msg("Unable to get gworld from grabber\n"); return 0; } if (SGNewChannel(s->grabber, VideoMediaType, &s->video_channel) != noErr) { debug_msg("Unable to open video channel\n"); return 0; } /* do not check for grab audio in case that we will only display usage */ if (SGNewChannel(s->grabber, SoundMediaType, &s->audio_channel) != noErr) { fprintf(stderr, "Warning: Creating audio channel failed. " "Disabling sound output.\n"); s->grab_audio = FALSE; } /* Print available devices */ int i; int j; SGDeviceInputList inputList; SGDeviceList deviceList; if (strcmp(fmt, "help") == 0) { printf("\nUsage:\t-t quicktime:<device>:<mode>:<pixel_type>[:<audio_device>:<audio_mode>]\n\n"); if (SGGetChannelDeviceList (s->video_channel, sgDeviceListIncludeInputs, &deviceList) == noErr) { fprintf(stdout, "\nAvailable capture devices:\n"); for (i = 0; i < (*deviceList)->count; i++) { SGDeviceName *deviceEntry = &(*deviceList)->entry[i]; fprintf(stdout, " Device %d: ", i); nprintf((char *) deviceEntry->name); if (deviceEntry->flags & sgDeviceNameFlagDeviceUnavailable) { fprintf(stdout, " - ### NOT AVAILABLE ###"); } if (i == (*deviceList)->selectedIndex) { fprintf(stdout, " - ### ACTIVE ###"); } fprintf(stdout, "\n"); short activeInputIndex = 0; inputList = deviceEntry->inputs; if (inputList && (*inputList)->count >= 1) { SGGetChannelDeviceAndInputNames (s->video_channel, NULL, NULL, &activeInputIndex); for (j = 0; j < (*inputList)->count; j++) { fprintf(stdout, "\t"); fprintf(stdout, "- %d. ", j); nprintf((char *) &(*inputList)->entry [j].name); if ((i == (*deviceList)->selectedIndex) && (j == activeInputIndex)) fprintf(stdout, " - ### ACTIVE ###"); fprintf(stdout, "\n"); } } } SGDisposeDeviceList(s->grabber, deviceList); CodecNameSpecListPtr list; GetCodecNameList(&list, 1); printf("\nCompression types:\n"); for (i = 0; i < list->count; i++) { int fcc = list->list[i].cType; printf("\t%d) ", i); nprintf((char *) list->list[i].typeName); printf(" - FCC (%c%c%c%c)", fcc >> 24, (fcc >> 16) & 0xff, (fcc >> 8) & 0xff, (fcc) & 0xff); printf(" - codec id %x", (unsigned int)(list->list[i].codec)); printf(" - cType %x", (unsigned int)list->list[i].cType); printf("\n"); } }
void pix_videoDarwin :: InitSeqGrabber() { OSErr anErr; Rect m_srcRect = {0,0, m_vidYSize, m_vidXSize}; SGDeviceList devices; short deviceIndex,inputIndex; short deviceCount = 0; SGDeviceInputList theSGInputList = NULL; bool showInputsAsDevices; // UserData *uD; /* int num_components = 0; Component c = 0; ComponentDescription cd; cd.componentType = SeqGrabComponentType; cd.componentSubType = 0; cd.componentManufacturer = 0; cd.componentFlags = 0; cd.componentFlagsMask = 0; while((c = FindNextComponent(c, &cd)) != 0) { num_components++; } // add component c to the list. // post("number of SGcomponents: %d",num_components); */ m_sg = OpenDefaultComponent(SeqGrabComponentType, 0); if(m_sg==NULL){ error("could not open default component"); return; } anErr = SGInitialize(m_sg); if(anErr!=noErr){ error("could not initialize SG error %d",anErr); return; } anErr = SGSetDataRef(m_sg, 0, 0, seqGrabDontMakeMovie); if (anErr != noErr){ error("dataref failed with error %d",anErr); } anErr = SGNewChannel(m_sg, VideoMediaType, &m_vc); if(anErr!=noErr){ error("could not make new SG channnel error %d",anErr); return; } anErr = SGGetChannelDeviceList(m_vc, sgDeviceListIncludeInputs, &devices); if(anErr!=noErr){ error("could not get SG channnel Device List"); }else{ deviceCount = (*devices)->count; deviceIndex = (*devices)->selectedIndex; logpost(NULL, 3, "SG channnel Device List count %d index %d",deviceCount,deviceIndex); int i; for (i = 0; i < deviceCount; i++){ logpost(NULL, 3, "SG channnel Device List %.*s", (*devices)->entry[i].name[0], (*devices)->entry[i].name+1); } SGGetChannelDeviceAndInputNames(m_vc, NULL, NULL, &inputIndex); showInputsAsDevices = ((*devices)->entry[deviceIndex].flags) & sgDeviceNameFlagShowInputsAsDevices; theSGInputList = ((SGDeviceName *)(&((*devices)->entry[deviceIndex])))->inputs; //fugly //we should have device names in big ass undocumented structs //walk through the list //for (i = 0; i < deviceCount; i++){ for (i = 0; i < inputIndex; i++){ logpost(NULL, 3, "SG channnel Input Device List %d %.*s", i, (*theSGInputList)->entry[i].name[0], (*theSGInputList)->entry[i].name+1); } } //this call sets the input device if (m_inputDevice > 0 && m_inputDevice < deviceCount) //check that the device is not out of bounds //anErr = SGSetChannelDeviceInput(m_vc,m_inputDevice); logpost(NULL, 3, "SGSetChannelDevice trying %s", (*devices)->entry[m_inputDevice].name[0], (*devices)->entry[m_inputDevice].name+1); anErr = SGSetChannelDevice(m_vc, (*devices)->entry[m_inputDevice].name); if(anErr!=noErr) error("SGSetChannelDevice returned error %d",anErr); anErr = SGSetChannelDeviceInput(m_vc,m_inputDeviceChannel); if(anErr!=noErr) error("SGSetChannelDeviceInput returned error %d",anErr); /* //attempt to save SG settings to disk NewUserData(uD); SGGetSettings(m_sg,uD,0); short uDCount; uDCount = CountUserDataType(*uD,sgClipType); post("UserDataType count %d",uDCount); Handle myHandle; PutUserDataIntoHandle(*uD,myHandle); int myFile; myFile = open("/Users/lincoln/Documents/temp",O_CREAT | O_RDWR, 0600); write(myFile,myHandle,4096); close(myFile); */ //grab the VDIG info from the SGChannel m_vdig = SGGetVideoDigitizerComponent(m_vc); vdigErr = VDGetDigitizerInfo(m_vdig,&m_vdigInfo); //not sure if this is useful Str255 vdigName; memset(vdigName,0,255); vdigErr = VDGetInputName(m_vdig,m_inputDevice,vdigName); logpost(NULL, 3, "vdigName is %s",vdigName); // pascal string? Rect vdRect; vdigErr = VDGetDigitizerRect(m_vdig,&vdRect); logpost(NULL, 3, "digitizer rect is top %d bottom %d left %d right %d",vdRect.top,vdRect.bottom,vdRect.left,vdRect.right); vdigErr = VDGetActiveSrcRect(m_vdig,0,&vdRect); logpost(NULL, 3, "active src rect is top %d bottom %d left %d right %d",vdRect.top,vdRect.bottom,vdRect.left,vdRect.right); anErr = SGSetChannelBounds(m_vc, &m_srcRect); if(anErr!=noErr){ error("could not set SG ChannelBounds "); } anErr = SGSetVideoRect(m_vc, &m_srcRect); if(anErr!=noErr){ error("could not set SG Rect "); } anErr = SGSetChannelUsage(m_vc, seqGrabPreview); if(anErr!=noErr){ error("could not set SG ChannelUsage "); } switch (m_quality){ case 0: anErr = SGSetChannelPlayFlags(m_vc, channelPlayNormal); post("set SG NormalQuality"); break; case 1: anErr = SGSetChannelPlayFlags(m_vc, channelPlayHighQuality); post("set SG HighQuality"); break; case 2: anErr = SGSetChannelPlayFlags(m_vc, channelPlayFast); post("set SG FastQuality"); break; case 3: anErr = SGSetChannelPlayFlags(m_vc, channelPlayAllData); post("set SG PlayAlldata"); break; } if (m_colorspace==GL_BGRA_EXT){ m_pixBlock.image.xsize = m_vidXSize; m_pixBlock.image.ysize = m_vidYSize; m_pixBlock.image.setCsizeByFormat(GL_RGBA_GEM); m_pixBlock.image.reallocate(); m_rowBytes = m_vidXSize*4; anErr = QTNewGWorldFromPtr (&m_srcGWorld, k32ARGBPixelFormat, &m_srcRect, NULL, NULL, 0, m_pixBlock.image.data, m_rowBytes); post ("using RGB"); }else{ m_pixBlock.image.xsize = m_vidXSize; m_pixBlock.image.ysize = m_vidYSize; m_pixBlock.image.csize = 2; m_pixBlock.image.format = GL_YCBCR_422_APPLE; #ifdef __VEC__ m_pixBlock.image.type = GL_UNSIGNED_SHORT_8_8_REV_APPLE; #else m_pixBlock.image.type = GL_UNSIGNED_SHORT_8_8_APPLE; #endif m_pixBlock.image.reallocate(); m_rowBytes = m_vidXSize*2; anErr = QTNewGWorldFromPtr (&m_srcGWorld, // k422YpCbCr8CodecType, k422YpCbCr8PixelFormat, // '2vuy', // kComponentVideoUnsigned, &m_srcRect, NULL, NULL, 0, m_pixBlock.image.data, m_rowBytes); post ("using YUV"); } if (anErr!= noErr) { error("%d error at QTNewGWorldFromPtr", anErr); return; } if (NULL == m_srcGWorld) { error("could not allocate off screen"); return; } SGSetGWorld(m_sg,(CGrafPtr)m_srcGWorld, NULL); SGStartPreview(m_sg); //moved to starttransfer? m_haveVideo = 1; }
bool macsgCamera::initCamera(int width, int height, bool colour) { if (cameraID < 0) return false; this->width = width; this->height = height; this->colour = colour; this->fps = 30; bytes = (colour?3:1); int rowlength= width*bytes; switch (colour) { case false: { pixelFormat = k8IndexedGrayPixelFormat; //pixelFormat = kYVYU422PixelFormat; break; } case true: { pixelFormat = k24RGBPixelFormat; break; } } OSErr result; Rect srcRect = {0,0, height, width}; sg = OpenDefaultComponent(SeqGrabComponentType, 0); if(sg==NULL){ fprintf(stderr, "could not open default component\n"); } result = SGInitialize(sg); if(result!=noErr){ fprintf(stdout, "could not initialize SG\n"); } result = SGSetDataRef(sg, 0, 0, seqGrabDontMakeMovie); if (result != noErr){ fprintf(stdout, "dataref failed\n"); } result = SGNewChannel(sg, VideoMediaType, &vc); if(result!=noErr){ //fprintf(stdout, "could not make new SG channnel\n"); return false; } // result = SGSettingsDialog ( sg, vc ,0 ,NULL ,seqGrabSettingsPreviewOnly,NULL,0); // if(result!=noErr){ // fprintf(stdout, "could not get settings from dialog\n"); // } result = SGSetChannelBounds(vc, &srcRect); if(result!=noErr){ fprintf(stdout, "could not set SG ChannelBounds\n"); } /*result = SGSetFrameRate (vc, fps); if(result!=noErr){ fprintf(stdout, "could not set SG FrameRate\n"); }*/ result = SGSetChannelUsage(vc, seqGrabPreview); if(result!=noErr){ fprintf(stdout, "could not set SG ChannelUsage\n"); } result = SGSetChannelPlayFlags(vc, channelPlayAllData); if(result!=noErr){ fprintf(stdout, "could not set SG AllData\n"); }; buffer = new unsigned char[width*height*bytes]; result = QTNewGWorldFromPtr (&srcGWorld, pixelFormat, &srcRect, NULL, NULL, 0, buffer, rowlength); if (result!= noErr) { fprintf(stdout, "%d error at QTNewGWorldFromPtr\n", result); delete []buffer; buffer = NULL; return false; } if (srcGWorld == NULL) { fprintf(stdout, "Could not allocate off screen\n"); delete []buffer; buffer = NULL; return false; } result = SGSetGWorld(sg,(CGrafPtr)srcGWorld, NULL); if (result != noErr) { fprintf(stdout, "Could not set SGSetGWorld\n"); delete []buffer; buffer = NULL; return false; } result = SGPrepare(sg, TRUE, FALSE); if (result != noErr) { fprintf(stderr, "SGPrepare Preview failed\n"); } pbuffer = new unsigned char[width*height*bytes]; return true; }
void QTCmpr_CompressSequence (WindowObject theWindowObject) { ComponentInstance myComponent = NULL; GWorldPtr myImageWorld = NULL; // the graphics world we draw the images in PixMapHandle myPixMap = NULL; Movie mySrcMovie = NULL; Track mySrcTrack = NULL; Movie myDstMovie = NULL; Track myDstTrack = NULL; Media myDstMedia = NULL; Rect myRect; PicHandle myPicture = NULL; CGrafPtr mySavedPort = NULL; GDHandle mySavedDevice = NULL; SCTemporalSettings myTimeSettings; SCDataRateSettings myRateSettings; FSSpec myFile; Boolean myIsSelected = false; Boolean myIsReplacing = false; short myRefNum = -1; StringPtr myMoviePrompt = QTUtils_ConvertCToPascalString(kQTCSaveMoviePrompt); StringPtr myMovieFileName = QTUtils_ConvertCToPascalString(kQTCSaveMovieFileName); MatrixRecord myMatrix; ImageDescriptionHandle myImageDesc = NULL; TimeValue myCurMovieTime = 0L; TimeValue myOrigMovieTime = 0L; // current movie time, when compression is begun short myFrameNum; long myFlags = 0L; long myNumFrames = 0L; long mySrcMovieDuration = 0L; // duration of source movie OSErr myErr = noErr; #if USE_ASYNC_COMPRESSION ICMCompletionProcRecord myICMComplProcRec; ICMCompletionProcRecordPtr myICMComplProcPtr = NULL; OSErr myICMComplProcErr = noErr; myICMComplProcRec.completionProc = NULL; myICMComplProcRec.completionRefCon = 0L; #endif if (theWindowObject == NULL) goto bail; ////////// // // get the movie and the first video track in the movie // ////////// mySrcMovie = (**theWindowObject).fMovie; if (mySrcMovie == NULL) goto bail; mySrcTrack = GetMovieIndTrackType(mySrcMovie, 1, VideoMediaType, movieTrackMediaType); if (mySrcTrack == NULL) goto bail; // stop the movie; we don't want it to be playing while we're (re)compressing it SetMovieRate(mySrcMovie, (Fixed)0L); // get the current movie time, when compression is begun; we'll restore this later myOrigMovieTime = GetMovieTime(mySrcMovie, NULL); ////////// // // configure and display the Standard Image Compression dialog box // ////////// // open an instance of the Standard Image Compression dialog component myComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); if (myComponent == NULL) goto bail; // turn off "best depth" option in the compression dialog, because all of our // buffering is done at 32-bits (regardless of the depth of the source data) // // a more ambitious approach would be to loop through each of the video sample // descriptions in each of the video tracks looking for the deepest depth, and // using that for the best depth; better yet, we could find out which compressors // were used and set one of those as the default in the compression dialog SCGetInfo(myComponent, scPreferenceFlagsType, &myFlags); myFlags &= ~scShowBestDepth; SCSetInfo(myComponent, scPreferenceFlagsType, &myFlags); // because we are recompressing a movie that may have a variable frame rate, // we want to allow the user to leave the frame rate text field blank (in which // case we can preserve the frame durations of the source movie); if the user // enters a number, we will resample the movie at a new frame rate; if we don't // clear this flag, the compression dialog will not allow zero in the frame rate field // // NOTE: we could have set this flag above when we cleared the scShowBestDepth flag; // it is done here for clarity. SCGetInfo(myComponent, scPreferenceFlagsType, &myFlags); myFlags |= scAllowZeroFrameRate; SCSetInfo(myComponent, scPreferenceFlagsType, &myFlags); // get the number of video frames in the movie myNumFrames = QTUtils_GetFrameCount(mySrcTrack); // get the bounding rectangle of the movie, create a 32-bit GWorld with those // dimensions, and draw the movie poster picture into it; this GWorld will be // used for the test image in the compression dialog box and for rendering movie // frames myPicture = GetMoviePosterPict(mySrcMovie); if (myPicture == NULL) goto bail; GetMovieBox(mySrcMovie, &myRect); myErr = NewGWorld(&myImageWorld, 32, &myRect, NULL, NULL, 0L); if (myErr != noErr) goto bail; // get the pixmap of the GWorld; we'll lock the pixmap, just to be safe myPixMap = GetGWorldPixMap(myImageWorld); if (!LockPixels(myPixMap)) goto bail; // draw the movie poster image into the GWorld GetGWorld(&mySavedPort, &mySavedDevice); SetGWorld(myImageWorld, NULL); EraseRect(&myRect); DrawPicture(myPicture, &myRect); KillPicture(myPicture); SetGWorld(mySavedPort, mySavedDevice); // set the picture to be displayed in the dialog box; passing NULL for the rect // means use the entire image; passing 0 for the flags means to use the default // system method of displaying the test image, which is currently a combination // of cropping and scaling; personally, I prefer scaling (your mileage may vary) SCSetTestImagePixMap(myComponent, myPixMap, NULL, scPreferScaling); // install the custom procs, if requested // we can install two kinds of custom procedures for use in connection with // the standard dialog box: (1) a modal-dialog filter function, and (2) a hook // function to handle the custom button in the dialog box if (gUseExtendedProcs) QTCmpr_InstallExtendedProcs(myComponent, (long)myPixMap); // set up some default settings for the compression dialog SCDefaultPixMapSettings(myComponent, myPixMap, true); // clear out the default frame rate chosen by Standard Compression (a frame rate // of 0 means to use the rate of the source movie) myErr = SCGetInfo(myComponent, scTemporalSettingsType, &myTimeSettings); if (myErr != noErr) goto bail; myTimeSettings.frameRate = 0; SCSetInfo(myComponent, scTemporalSettingsType, &myTimeSettings); // request image compression settings from the user; in other words, put up the dialog box myErr = SCRequestSequenceSettings(myComponent); if (myErr == scUserCancelled) goto bail; // get a copy of the temporal settings the user entered; we'll need them for some // of our calculations (in a simpler application, we'd never have to look at them) SCGetInfo(myComponent, scTemporalSettingsType, &myTimeSettings); ////////// // // adjust the data rate [to be supplied][relevant only for movies that have sound tracks] // ////////// ////////// // // adjust the sample count // // if the user wants to resample the frame rate of the movie (as indicated a non-zero // value in the frame rate field) calculate the number of frames and duration for the new movie // ////////// if (myTimeSettings.frameRate != 0) { long myDuration = GetMovieDuration(mySrcMovie); long myTimeScale = GetMovieTimeScale(mySrcMovie); float myFloat = (float)myDuration * myTimeSettings.frameRate; myNumFrames = myFloat / myTimeScale / 65536; if (myNumFrames == 0) myNumFrames = 1; } ////////// // // get the name and location of the new movie file // ////////// // prompt the user for a file to put the compressed image into; in theory, the name // should have a file extension appropriate to the type of compressed data selected by the user; // this is left as an exercise for the reader QTFrame_PutFile(myMoviePrompt, myMovieFileName, &myFile, &myIsSelected, &myIsReplacing); if (!myIsSelected) goto bail; // delete any existing file of that name if (myIsReplacing) { myErr = DeleteMovieFile(&myFile); if (myErr != noErr) goto bail; } ////////// // // create the target movie // ////////// myErr = CreateMovieFile(&myFile, sigMoviePlayer, smSystemScript, createMovieFileDeleteCurFile | createMovieFileDontCreateResFile, &myRefNum, &myDstMovie); if (myErr != noErr) goto bail; // create a new video movie track with the same dimensions as the entire source movie myDstTrack = NewMovieTrack(myDstMovie, (long)(myRect.right - myRect.left) << 16, (long)(myRect.bottom - myRect.top) << 16, kNoVolume); if (myDstTrack == NULL) goto bail; // create a media for the new track with the same time scale as the source movie; // because the time scales are the same, we don't have to do any time scale conversions. myDstMedia = NewTrackMedia(myDstTrack, VIDEO_TYPE, GetMovieTimeScale(mySrcMovie), 0, 0); if (myDstMedia == NULL) goto bail; // copy the user data and settings from the source to the dest movie CopyMovieSettings(mySrcMovie, myDstMovie); // set movie matrix to identity and clear the movie clip region (because the conversion // process transforms and composites all video tracks into one untransformed video track) SetIdentityMatrix(&myMatrix); SetMovieMatrix(myDstMovie, &myMatrix); SetMovieClipRgn(myDstMovie, NULL); // set the movie to highest quality imaging SetMoviePlayHints(mySrcMovie, hintsHighQuality, hintsHighQuality); myImageDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription)); if (myImageDesc == NULL) goto bail; // prepare for adding frames to the movie myErr = BeginMediaEdits(myDstMedia); if (myErr != noErr) goto bail; ////////// // // compress the image sequence // // we are going to step through the source movie, compress each frame, and then add // the compressed frame to the destination movie // ////////// myErr = SCCompressSequenceBegin(myComponent, myPixMap, NULL, &myImageDesc); if (myErr != noErr) goto bail; #if USE_ASYNC_COMPRESSION myFlags = codecFlagUpdatePrevious + codecFlagUpdatePreviousComp + codecFlagLiveGrab; SCSetInfo(myComponent, scCodecFlagsType, &myFlags); #endif // clear out our image GWorld and set movie to draw into it SetGWorld(myImageWorld, NULL); EraseRect(&myRect); SetMovieGWorld(mySrcMovie, myImageWorld, GetGWorldDevice(myImageWorld)); // set current time value to beginning of the source movie myCurMovieTime = 0; // get a value we'll need inside the loop mySrcMovieDuration = GetMovieDuration(mySrcMovie); // loop through all of the interesting times we counted above for (myFrameNum = 0; myFrameNum < myNumFrames; myFrameNum++) { short mySyncFlag; TimeValue myDuration; long myDataSize; Handle myCompressedData; ////////// // // get the next frame of the source movie // ////////// // if we are resampling the movie, step to the next frame if (myTimeSettings.frameRate) { myCurMovieTime = myFrameNum * mySrcMovieDuration / (myNumFrames - 1); myDuration = mySrcMovieDuration / myNumFrames; } else { OSType myMediaType = VIDEO_TYPE; myFlags = nextTimeMediaSample; // if this is the first frame, include the frame we are currently on if (myFrameNum == 0) myFlags |= nextTimeEdgeOK; // if we are maintaining the frame durations of the source movie, // skip to the next interesting time and get the duration for that frame GetMovieNextInterestingTime(mySrcMovie, myFlags, 1, &myMediaType, myCurMovieTime, 0, &myCurMovieTime, &myDuration); } SetMovieTimeValue(mySrcMovie, myCurMovieTime); MoviesTask(mySrcMovie, 0); MoviesTask(mySrcMovie, 0); MoviesTask(mySrcMovie, 0); // if data rate constraining is being done, tell Standard Compression the // duration of the current frame in milliseconds; we only need to do this // if the frames have variable durations if (!SCGetInfo(myComponent, scDataRateSettingsType, &myRateSettings)) { myRateSettings.frameDuration = myDuration * 1000 / GetMovieTimeScale(mySrcMovie); SCSetInfo(myComponent, scDataRateSettingsType, &myRateSettings); } ////////// // // compress the current frame of the source movie and add it to the destination movie // ////////// // if SCCompressSequenceFrame completes successfully, myCompressedData will hold // a handle to the newly-compressed image data and myDataSize will be the size of // the compressed data (which will usually be different from the size of the handle); // also mySyncFlag will be a value that that indicates whether or not the frame is a // key frame (and which we pass directly to AddMediaSample); note that we do not need // to dispose of myCompressedData, since SCCompressSequenceEnd will do that for us #if !USE_ASYNC_COMPRESSION myErr = SCCompressSequenceFrame(myComponent, myPixMap, &myRect, &myCompressedData, &myDataSize, &mySyncFlag); if (myErr != noErr) goto bail; #else if (myICMComplProcPtr == NULL) { myICMComplProcRec.completionProc = NewICMCompletionProc(QTCmpr_CompletionProc); myICMComplProcRec.completionRefCon = (long)&myICMComplProcErr; myICMComplProcPtr = &myICMComplProcRec; } myICMComplProcErr = kAsyncDefaultValue; myErr = SCCompressSequenceFrameAsync(myComponent, myPixMap, &myRect, &myCompressedData, &myDataSize, &mySyncFlag, myICMComplProcPtr); if (myErr != noErr) goto bail; // spin our wheels while we're waiting for the compress call to complete while (myICMComplProcErr == kAsyncDefaultValue) { EventRecord myEvent; WaitNextEvent(0, &myEvent, 60, NULL); SCAsyncIdle(myComponent); } myErr = myICMComplProcErr; #endif myErr = AddMediaSample(myDstMedia, myCompressedData, 0, myDataSize, myDuration, (SampleDescriptionHandle)myImageDesc, 1, mySyncFlag, NULL); if (myErr != noErr) goto bail; } // close the compression sequence; this will dispose of the image description // and compressed data handles allocated by SCCompressSequenceBegin SCCompressSequenceEnd(myComponent); ////////// // // add the media data to the destination movie // ////////// myErr = EndMediaEdits(myDstMedia); if (myErr != noErr) goto bail; InsertMediaIntoTrack(myDstTrack, 0, 0, GetMediaDuration(myDstMedia), fixed1); // add the movie resource to the dst movie file. myErr = AddMovieResource(myDstMovie, myRefNum, NULL, NULL); if (myErr != noErr) goto bail; // flatten the movie data [to be supplied] // close the movie file CloseMovieFile(myRefNum); bail: // close the Standard Compression component if (myComponent != NULL) CloseComponent(myComponent); if (mySrcMovie != NULL) { // restore the source movie's original graphics port and device SetMovieGWorld(mySrcMovie, mySavedPort, mySavedDevice); // restore the source movie's original movie time SetMovieTimeValue(mySrcMovie, myOrigMovieTime); } // restore the original graphics port and device SetGWorld(mySavedPort, mySavedDevice); // delete the GWorld we were drawing frames into if (myImageWorld != NULL) DisposeGWorld(myImageWorld); #if USE_ASYNC_COMPRESSION if (myICMComplProcRec.completionProc != NULL) DisposeICMCompletionUPP(myICMComplProcRec.completionProc); #endif free(myMoviePrompt); free(myMovieFileName); }