Offline Rendering with QCRenderer

Thomas Neugebauer's picture

Hello to everybody!

First of all, I am quite new to QC, but working with it for some weeks now "demystified" it a lot :-)

I already use QuartzCrystal to render QTZs into image-sequences. That works abs. fine but now I want basically to have more control over the image sequence (quality, format etc.) and also want to be able to include my own logic into the renderer (currently using a PHP wrapper to "control" the CLI version of QuartzCrystal).

So I looked into the "Quartz Composer Offline" example provided by Apple (

Based on that, I am able to render frames into JPEGs/PNGs - here my questions:

1) For 10.5 and above, it creates the offline renderer with

_renderer = [[QCRenderer alloc]  initOffScreenWithSize:NSMakeSize(width, height) colorSpace:colorSpace composition:composition];

Whereby for < 10.5, it uses

_renderer = [[QCRenderer alloc] initWithOpenGLContext:_openGLContext pixelFormat:format file:path];

Does it have any advantage in using the "initWidthOpenGLContext" approach?

2) I have noticed, that if my QTZ doesn't have a "clear patch" in it, I see some "garbage" in my frames. I understand that, that but want to know, if there is any way to do the "clear" in my "renderAtTime" loop in case, that I forget to include a "clear patch".

3) I am also trying to read a "published output" from the composition - therefore I implemented:

- (id) getPort:(NSString*)key ofType:(NSString*)type
   return[_renderer valueForOutputKey:key ofType:type];

Im my "renderAtTime" loop, I do a

NSLog(@"%d", [renderer getPort:@"Result" ofType:@"Number"]);

My test-comp publishes "Result" (a "Math expression", which returns 10 and which is connected to a "Sprite" via "Image with Text"), but "NSLog" always returns 0.

I guess, that I am at least doing something correct, otherwise I would expect an exception, if I try to read an outputkey, which is not published.

Looking forward for your help!

Thanks a lot! Thomas

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Thomas Neugebauer's picture
Re: Offline Rendering with QCRenderer

One comment regarding 3)

If I do a

- (id) getPort:(NSString*)key 
   return[_renderer valueForOutputKey:key];   

... it works fine - which solves my problem, but still I don't understand why it doesn't work with "ofType:@...".

vade's picture
Re: Offline Rendering with QCRenderer

Clear with OpenGL using


before you call [myRenderer executeAtTime:time arguments:args];

This ensure the content of the rendering destination is flushed with the current gl clear color and the depth buffer is also cleared. If you have a clear patch in the comp, you will effectively be doing this twice.

As for the difference between a OpenGL context being used and the initWithOffscreen initializer, my understanding is that initWithOffscreen uses a CGLPixelBuffer object and an internal GL context that the QCRenderer handles itself. Handing it a gl context means you are responsible for properly choosing the pixel format, setting the context up, making the context active and disposing of the context once you are done with it.

As for this port stuff, ive never looked at the offline renderer code, but typically you do something like

QCRenderer* myRenderer = [[QCRenderer alloc] initWithWhateverInitializerYouwant]
// set the input value for published input ports.
[myRenderer setValue:someVal forInputKey:someInputKey];
// for the patch to execute, this calculates the output port values at the passed in time, and the arguments should mouse/trackball etc patches be in the myRenderer composition.
[myRenderer executeAtTime:someTime arguments:someArguments];
// only now do output ports contain sane values
id someResultObject = [myRender valueForOutputKey:@"someKey" ofType:@"SomeType"];

valid types are: @"CIImage" @"NSBitMapImageRep", @"NSNumber" , @"NSString", etc,

not "Number", "String", "Image". Use the "className" method if you are unsure what to use/enter. That ought to work.

Thomas Neugebauer's picture
Re: Offline Rendering with QCRenderer

Thanks for your input!

In order to use "glClear", I must have the glContext - correct? How do I do that, if I use "QCRenderer" the easy way (by using "initWithOffscreen")?

Regarding ports: that would explain, why I always got (null) or "0" - sometimes, reading the documentation might help :-)


vade's picture
Re: Offline Rendering with QCRenderer

I highly suggest not putting in the glClear and using your own GL context, and just building proper working patches with a clear patch at layer 1.

Once you get into OpenGL, you are going to open up a world of hurt unless you are mentally and programmatically prepared for it. I suggest getting the fundamentals right before jumping into pandoras box head first without a flashlight.. so to speak :)

Also, yes, the documentation. Read it. :)

gtoledo3's picture
Re: Offline Rendering with QCRenderer

Even quicklook won't render comps correctly if they don't have a clear. Just assuming that a clear is needed, is probably a good idea; a blank with clear is considered a basic composition.

Thomas Neugebauer's picture
Re: Offline Rendering with QCRenderer

You are both right - I should take the easy "path" by deploying a "clear patch" rather than fighting with OpenGL, which looks like a pain in the ... :-)

Remembers me doing Xlib and Xt programming long time ago - lots of stuff to code before seeing something.

I came across the following issue while using "Movie Player" (the movie is basically a "motion PNG" within a mov-container) - everything renders fine into images, but I get:

2011-02-17 09:50:17.917 QTKitServer[73639:5503]  *** CVOpenGLTextureCache: Forced to manually upload an IOSurface backed pixel buffer because it uses a non-native pixel format. Break on CVOpenGLTextureCache_IOSurfaceNotInNativePixelFormat() to debug.
2011-02-17 09:50:17.935 rendrme[73637:903] *** Message from <QCQuickTimePlayer = 0x028AEFA0 "QuickTimePlayer_1">:
Failed retrieving image from movie <QTMovie: 0x1028cb350 time scale = 1000, duration = 5000, rate = 0.000000, tracks = { 0x103b7fd40 }> (error (null))
2011-02-17 09:50:17.936 rendrme[73637:903] *** Message from <QCQuickTimePlayer = 0x028AEFA0 "QuickTimePlayer_1">:
Execution failed at time 0.000

By accident, I found out, that I don't get this, if I compile as "i386" rather than "x86-64" - so can I simply ignore those messages as they might be related to different framework/library version for 64bit?

Again, thanks!