diff options
author | Rob Haarsma <phaseIV@zonnet.nl> | 2003-05-21 05:21:07 +0400 |
---|---|---|
committer | Rob Haarsma <phaseIV@zonnet.nl> | 2003-05-21 05:21:07 +0400 |
commit | 9662763ee0cf3d1176210d93e731e8a224622025 (patch) | |
tree | 863ee71a2db2da7ebc62ca3e98330a0de84855bb /source/blender | |
parent | 0bebdabad2419466dff1203fe95fad0280a034b2 (diff) |
Updated Quicktime code so settings can be stored in the blendfile.
This enables Blender to;
- have scenes with different codec settings. (same as avicodec)
- render directly without dialog.
- batch/background render to Quicktime movies.
Only tested on windows. ;)
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_scene.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 17 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 5 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 5 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 13 | ||||
-rw-r--r-- | source/blender/quicktime/apple/quicktime_export.c | 305 | ||||
-rw-r--r-- | source/blender/quicktime/quicktime_export.h | 3 | ||||
-rw-r--r-- | source/blender/quicktime/quicktime_import.h | 2 | ||||
-rw-r--r-- | source/blender/src/buttons.c | 6 | ||||
-rw-r--r-- | source/blender/src/headerbuttons.c | 15 |
10 files changed, 210 insertions, 162 deletions
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index a278cc0cfb1..3a0c17b5f31 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -40,6 +40,7 @@ struct Base; struct AviCodecData; void free_avicodecdata(struct AviCodecData *acd); +void free_qtcodecdata(struct QuicktimeCodecData *acd); void free_scene(struct Scene *me); struct Scene *add_scene(char *name); int object_in_scene(struct Object *ob, struct Scene *sce); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 44de11db7bb..c7989450870 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1,4 +1,3 @@ - /* scene.c * * @@ -101,6 +100,17 @@ void free_avicodecdata(AviCodecData *acd) } } +void free_qtcodecdata(QuicktimeCodecData *qcd) +{ + if (qcd) { + if (qcd->cdParms){ + MEM_freeN(qcd->cdParms); + qcd->cdParms = NULL; + qcd->cdSize = 0; + } + } +} + /* do not free scene itself */ void free_scene(Scene *sce) { @@ -125,6 +135,11 @@ void free_scene(Scene *sce) MEM_freeN(sce->r.avicodecdata); sce->r.avicodecdata = NULL; } + if (sce->r.qtcodecdata) { + free_qtcodecdata(sce->r.qtcodecdata); + MEM_freeN(sce->r.qtcodecdata); + sce->r.qtcodecdata = NULL; + } } Scene *add_scene(char *name) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f62d4a72b07..609b99b9f15 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2291,6 +2291,11 @@ static void direct_link_scene(FileData *fd, Scene *sce) sce->r.avicodecdata->lpParms = newdataadr(fd, sce->r.avicodecdata->lpParms); } + sce->r.qtcodecdata = newdataadr(fd, sce->r.qtcodecdata); + if (sce->r.qtcodecdata) { + sce->r.qtcodecdata->cdParms = newdataadr(fd, sce->r.qtcodecdata->cdParms); + } + if(sce->ed) { ed= sce->ed= newdataadr(fd, sce->ed); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index c7db707cceb..640e5333023 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1164,6 +1164,11 @@ static void write_scenes(WriteData *wd, ListBase *scebase) if (sce->r.avicodecdata->lpParms) writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms); } + if (sce->r.qtcodecdata) { + writestruct(wd, DATA, "QuicktimeCodecData", 1, sce->r.qtcodecdata); + if (sce->r.qtcodecdata->cdParms) writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms); + } + sce= sce->id.next; } } diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index afe0d5f5ab8..c15b34def92 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -81,8 +81,21 @@ typedef struct AviCodecData { char avicodecname[128]; } AviCodecData; +typedef struct QuicktimeCodecData { + + void *cdParms; /* codec/compressor options */ + void *pad; /* padding */ + + unsigned int cdSize; /* size of cdParms buffer */ + unsigned int pad2; /* padding */ + + char qtcodecname[128]; +} QuicktimeCodecData; + + typedef struct RenderData { struct AviCodecData *avicodecdata; + struct QuicktimeCodecData *qtcodecdata; short cfra, sfra, efra; /* fames as in 'images' */ short images, framapto, flag; diff --git a/source/blender/quicktime/apple/quicktime_export.c b/source/blender/quicktime/apple/quicktime_export.c index 0bcc51db84a..724a6a6ba9b 100644 --- a/source/blender/quicktime/apple/quicktime_export.c +++ b/source/blender/quicktime/apple/quicktime_export.c @@ -31,22 +31,6 @@ * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* -TODO: - -- fix saving of compressionsettings - -This should be fixed because: - -- currently only one quicktime codec is used for all scenes -- this single codecsetting gets only initialised from the codec dialog - -- the codecsettings have to get stored in the blendfile for background - rendering. blender -b crashes when it wants to popup the qt codec dialog - to retrieve a valid codec. -(quicktime isnt initialised yet when blender -b requests a rendering codec) - -Some references to store the codec settings are placed at the end of this file. - DONE: * structurize file & compression data @@ -58,6 +42,7 @@ DONE: * fix fallthrough to codecselector // buttons.c * fix playback qt movie // playanim.c * fix setting fps thru blenderbutton as well as codec dialog +* fix saving of compressionsettings */ @@ -153,7 +138,8 @@ typedef struct _QuicktimeCodecDataExt { TimeValue duration; long kVideoTimeScale; -} QuicktimeCodecDataExt; +} QuicktimeCodecDataExt; //qtopts + struct _QuicktimeExport *qte; struct _QuicktimeCodecDataExt *qcdx; @@ -169,10 +155,118 @@ struct _QuicktimeCodecDataExt *qcdx; #define kTrackStart 0 #define kMediaStart 0 -static int sframe; +static int sframe; +static char qtcdname[128]; + + +/************************************************************ +* * +* SaveExporterSettingsToMem * +* * +*************************************************************/ + +OSErr SaveExporterSettingsToMem (QuicktimeCodecData *qcd) +{ + QTAtomContainer myContainer = NULL; + ComponentResult myErr = noErr; + Ptr myPtr; + Handle myHandle; + long mySize = 0; + + // check if current scene already has qtcodec settings, and erase them + if (qcd) { + free_qtcodecdata(qcd); + } else { + qcd = G.scene->r.qtcodecdata = MEM_callocN(sizeof(QuicktimeCodecData), "QuicktimeCodecData"); + } + + // obtain all current codec settings + SCSetInfo(qcdx->theComponent, scTemporalSettingsType, &qcdx->gTemporalSettings); + SCSetInfo(qcdx->theComponent, scSpatialSettingsType, &qcdx->gSpatialSettings); + SCSetInfo(qcdx->theComponent, scDataRateSettingsType, &qcdx->aDataRateSetting); + + // retreive codecdata from quicktime in a atomcontainer + myErr = SCGetSettingsAsAtomContainer(qcdx->theComponent, &myContainer); + if (myErr != noErr) { + printf("Quicktime: SCGetSettingsAsAtomContainer failed\n"); + goto bail; + } + + // get the size of the atomcontainer + mySize = GetHandleSize((Handle)myContainer); + + // lock and convert the atomcontainer to a *valid* pointer + QTLockContainer(myContainer); + myHandle = (Handle) myContainer; + HLockHi(myHandle); + myPtr = *myHandle; + + // copy the Quicktime data into the blender qtcodecdata struct + if (myPtr) { + qcd->cdParms = MEM_mallocN(mySize, "qt.cdParms"); + memcpy(qcd->cdParms, myPtr, mySize); + qcd->cdSize = mySize; + sprintf(qcd->qtcodecname, qtcdname); + } else { + printf("Quicktime: SaveExporterSettingsToMem failed\n"); + } + + QTUnlockContainer(myContainer); + +bail: + if (myHandle != NULL) + DisposeHandle(myHandle); + if (myContainer != NULL) + QTDisposeAtomContainer(myContainer); + + return((OSErr)myErr); +} + +/************************************************************ +* * +* GetExporterSettingsFromMem * +* * +*************************************************************/ + +OSErr GetExporterSettingsFromMem (QuicktimeCodecData *qcd) +{ + Handle myHandle = NULL; + ComponentResult myErr = noErr; +// CodecInfo ci; +// char str[255]; + + // if there is codecdata in the blendfile, convert it to a Quicktime handle + if (qcd) { + myHandle = NewHandle(qcd->cdSize); + PtrToHand( qcd->cdParms, &myHandle, qcd->cdSize); + } + + // restore codecsettings to the quicktime component + if(qcd->cdParms && qcd->cdSize) { + myErr = SCSetSettingsFromAtomContainer((GraphicsExportComponent)qcdx->theComponent, (QTAtomContainer)myHandle); + if (myErr != noErr) { + printf("Quicktime: SCSetSettingsFromAtomContainer failed\n"); + goto bail; + } + + // update runtime codecsettings for use with the codec dialog + SCGetInfo(qcdx->theComponent, scDataRateSettingsType, &qcdx->aDataRateSetting); + SCGetInfo(qcdx->theComponent, scSpatialSettingsType, &qcdx->gSpatialSettings); + SCGetInfo(qcdx->theComponent, scTemporalSettingsType, &qcdx->gTemporalSettings); + +// GetCodecInfo (&ci, qcdx->gSpatialSettings.codecType, 0); +// CopyPascalStringToC(ci.typeName, str); +// printf("restored Codec: %s\n", str); + } else { + printf("Quicktime: GetExporterSettingsFromMem failed\n"); + } +bail: + if (myHandle != NULL) + DisposeHandle(myHandle); + + return((OSErr)myErr); +} -int have_qtcodec; -char qtcdname[64]; /************************************************************ * * @@ -356,10 +450,8 @@ static void QT_EndAddVideoSamplesToMedia (void) UnlockPixels(qte->thePixMap); if (qte->theGWorld) DisposeGWorld (qte->theGWorld); - if (qte->ibuf) IMB_freeImBuf(qte->ibuf); - if (qte->ibuf2) { - IMB_freeImBuf(qte->ibuf2); - } + if (qte->ibuf) IMB_freeImBuf(qte->ibuf); + if (qte->ibuf2) IMB_freeImBuf(qte->ibuf2); } @@ -410,7 +502,23 @@ void start_qt(void) { #endif if(qte == NULL) qte = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); - if(qcdx == NULL || have_qtcodec == FALSE) get_qtcodec_settings(); + + if(qcdx) { + if(qcdx->theComponent) CloseComponent(qcdx->theComponent); + free_qtcodecdataExt(); + } + + qcdx = MEM_callocN(sizeof(QuicktimeCodecDataExt), "QuicktimeCodecDataExt"); + + if(G.scene->r.qtcodecdata == NULL && G.scene->r.qtcodecdata->cdParms == NULL) { + get_qtcodec_settings(); + } else { + qcdx->theComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); + +// printf("getting from blend\n"); + GetExporterSettingsFromMem (G.scene->r.qtcodecdata); + check_renderbutton_framerate(); + } if (G.afbreek != 1) { sframe = (G.scene->r.sfra); @@ -445,8 +553,6 @@ void start_qt(void) { printf("Created QuickTime movie: %s\n", name); - check_renderbutton_framerate(); - QT_CreateMyVideoTrack(); } } @@ -489,6 +595,7 @@ void end_qt(void) { void free_qtcodecdataExt(void) { if(qcdx) { + if(qcdx->theComponent) CloseComponent(qcdx->theComponent); MEM_freeN(qcdx); qcdx = NULL; } @@ -508,7 +615,7 @@ static void check_renderbutton_framerate(void) { OSErr err; err = SCGetInfo(qcdx->theComponent, scTemporalSettingsType, &qcdx->gTemporalSettings); - CheckError(err, "SCGetInfo error"); + CheckError(err, "SCGetInfo fr error"); if( (G.scene->r.frs_sec == 24 || G.scene->r.frs_sec == 30 || G.scene->r.frs_sec == 60) && (qcdx->gTemporalSettings.frameRate == 1571553 || @@ -533,6 +640,7 @@ static void check_renderbutton_framerate(void) { qcdx->duration = 100; } } + /******************************************************************** * * * get_qtcodec_settings() * @@ -544,29 +652,28 @@ static void check_renderbutton_framerate(void) { int get_qtcodec_settings(void) { OSErr err = noErr; -// Component c = 0; -// ComponentDescription cd; CodecInfo ci; char str[255]; -// cd.componentType = StandardCompressionType; -// cd.componentSubType = StandardCompressionSubType; -// cd.componentManufacturer = 0; -// cd.componentFlags = 0; -// cd.componentFlagsMask = 0; - - if(qcdx == NULL) { - qcdx = MEM_callocN(sizeof(QuicktimeCodecDataExt), "QuicktimeCodecDataExt"); - have_qtcodec = FALSE; + // erase any existing codecsetting + if(qcdx) { + if(qcdx->theComponent) CloseComponent(qcdx->theComponent); + free_qtcodecdataExt(); } - // configure the standard image compression dialog box + // allocate new + qcdx = MEM_callocN(sizeof(QuicktimeCodecDataExt), "QuicktimeCodecDataExt"); + qcdx->theComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); - if (qcdx->theComponent == NULL) { - qcdx->theComponent = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); -// c = FindNextComponent(c, &cd); -// qcdx->theComponent = OpenComponent(c); + // get previous selected codecsetting, if any + if(G.scene->r.qtcodecdata && G.scene->r.qtcodecdata->cdParms) { +// printf("getting from MEM\n"); + GetExporterSettingsFromMem (G.scene->r.qtcodecdata); + check_renderbutton_framerate(); + } else { + // configure the standard image compression dialog box + // set some default settings // qcdx->gSpatialSettings.codecType = nil; qcdx->gSpatialSettings.codec = anyCodec; // qcdx->gSpatialSettings.depth; @@ -581,7 +688,6 @@ int get_qtcodec_settings(void) // qcdx->aDataRateSetting.minSpatialQuality; // qcdx->aDataRateSetting.minTemporalQuality; - err = SCSetInfo(qcdx->theComponent, scTemporalSettingsType, &qcdx->gTemporalSettings); CheckError(err, "SCSetInfo1 error"); err = SCSetInfo(qcdx->theComponent, scSpatialSettingsType, &qcdx->gSpatialSettings); @@ -589,11 +695,7 @@ int get_qtcodec_settings(void) err = SCSetInfo(qcdx->theComponent, scDataRateSettingsType, &qcdx->aDataRateSetting); CheckError(err, "SCSetInfo3 error"); } - - check_renderbutton_framerate(); - // put up the dialog box - err = SCRequestSequenceSettings(qcdx->theComponent); if (err == scUserCancelled) { @@ -601,10 +703,7 @@ int get_qtcodec_settings(void) return 0; } - have_qtcodec = TRUE; - // get user selected data - SCGetInfo(qcdx->theComponent, scTemporalSettingsType, &qcdx->gTemporalSettings); SCGetInfo(qcdx->theComponent, scSpatialSettingsType, &qcdx->gSpatialSettings); SCGetInfo(qcdx->theComponent, scDataRateSettingsType, &qcdx->aDataRateSetting); @@ -613,8 +712,9 @@ int get_qtcodec_settings(void) CopyPascalStringToC(ci.typeName, str); sprintf(qtcdname,"Codec: %s", str); - // framerate jugglin' + SaveExporterSettingsToMem(G.scene->r.qtcodecdata); + // framerate jugglin' if(qcdx->gTemporalSettings.frameRate == 1571553) { // 23.98 fps qcdx->kVideoTimeScale = 2398; qcdx->duration = 100; @@ -644,102 +744,3 @@ int get_qtcodec_settings(void) #endif /* WITH_QUICKTIME */ - - -#if 0 - -/************************************************************ -* * -* References for future codec handling * -* * -*************************************************************/ - -these are from mplayer sourcecode: - -struct ComponentRecord { - long data[1]; -}; -typedef struct ComponentRecord ComponentRecord; -typedef ComponentRecord * Component; -typedef long OSErr; -typedef int OSType; -typedef long ComponentResult; -typedef long Fixed; - - -these are from quicktime: - - -typedef Component CodecComponent; -typedef OSType CodecType; -typedef unsigned short CodecFlags; -typedef unsigned long CodecQ; - -typedef struct { - CodecType codecType; /* compressor type */ - CodecComponent codec; /* compressor */ - short depth; /* pixel depth */ - CodecQ spatialQuality; /* desired quality */ -} SCSpatialSettings; - -/* temporal options structure with the temporal settings request */ -typedef struct { - CodecQ temporalQuality; /* desired quality */ - Fixed frameRate; /* frame rate */ - long keyFrameRate; /* key frame rate */ -} SCTemporalSettings; - -/* data rate options with the data rate settings request */ -typedef struct { - long dataRate; /* desired data rate */ - long frameDuration; /* frame duration */ - CodecQ minSpatialQuality; /* minimum value */ - CodecQ minTemporalQuality; /* minimum value */ -} SCDataRateSettings; - - -would look like this ??? - -typedef struct { - int codecType; /* compressor type */ -//here is the prob - long *codec; /* compressor */ - short depth; /* pixel depth */ - unsigned long spatialQuality; /* desired quality */ -} SCSpatialSettings; - -/* temporal options structure with the temporal settings request */ -typedef struct { - unsigned long temporalQuality; /* desired quality */ - long frameRate; /* frame rate */ - long keyFrameRate; /* key frame rate */ -} SCTemporalSettings; - -/* data rate options with the data rate settings request */ -typedef struct { - long dataRate; /* desired data rate */ - long frameDuration; /* frame duration */ - unsigned long minSpatialQuality; /* minimum value */ - unsigned long minTemporalQuality; /* minimum value */ -} SCDataRateSettings; - - -stuff to use quicktime Atoms (doesnt work) heh - - long size; - Ptr thePtr; - QTAtomContainer myContainer = NULL; - QTAtom myAtom; -QTAtomContainer SettingsAtom; - -atom -> component -SCSetSettingsFromAtomContainer(qcdx->theComponent, SettingsAtom); - -component -> atom -SCGetSettingsAsAtomContainer(qcdx->theComponent, SettingsAtom); - -QTCopyAtomDataToPtr(container, atom, 0, size, &targetPtr, &actualsize); -QTGetAtomDataPtr(container, atom, &size, &ptr); - -kParentAtomIsContainer -#endif /* 0 */ diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h index 8d9d4a835d6..8153b7ba85f 100644 --- a/source/blender/quicktime/quicktime_export.h +++ b/source/blender/quicktime/quicktime_export.h @@ -45,9 +45,6 @@ void free_qtcodecdataExt(void); //usiblender.c void makeqtstring (char *string); //for playanim.c -extern int have_qtcodec; -extern char qtcdname[64]; - #endif //(_WIN32) || (__APPLE__) #endif // __QUICKTIME_IMP_H__ diff --git a/source/blender/quicktime/quicktime_import.h b/source/blender/quicktime/quicktime_import.h index 070346413a1..1289ffabd13 100644 --- a/source/blender/quicktime/quicktime_import.h +++ b/source/blender/quicktime/quicktime_import.h @@ -96,4 +96,4 @@ ImBuf *qtime_fetchibuf (struct anim *anim, int position); int imb_is_a_quicktime (char *name); ImBuf *imb_quicktime_decode(unsigned char *mem, int size, int flags); -#endif // __QUICKTIME_IMP_H__ +#endif // __QUICKTIME_IMP_H__
\ No newline at end of file diff --git a/source/blender/src/buttons.c b/source/blender/src/buttons.c index 6e55ad9fb97..5260df07cb9 100644 --- a/source/blender/src/buttons.c +++ b/source/blender/src/buttons.c @@ -6027,7 +6027,7 @@ void do_renderbuts(unsigned short event) if (((G.scene->r.imtype == R_AVICODEC) && (G.scene->r.avicodecdata == NULL)) || ((G.scene->r.imtype == R_QUICKTIME) - && (have_qtcodec == FALSE))) { + && (G.scene->r.qtcodecdata == NULL))) { } else { break; } @@ -6589,10 +6589,10 @@ void renderbuts(void) #if defined (_WIN32) || defined (__APPLE__) glColor3f(0.65, 0.65, 0.7); glRecti(892,yofs+46,892+225,yofs+45+20); - if(!have_qtcodec) + if(G.scene->r.qtcodecdata == NULL) uiDefBut(block, LABEL, 0, "Codec: not set", 892,yofs+44,225,20, 0, 0, 0, 0, 0, ""); else - uiDefBut(block, LABEL, 0, qtcdname, 892,yofs+44,225,20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, G.scene->r.qtcodecdata->qtcodecname, 892,yofs+44,225,20, 0, 0, 0, 0, 0, ""); uiDefBut(block, BUT,B_SELECTCODEC, "Set codec", 892,yofs,112,20, 0, 0, 0, 0, 0, "Set codec settings for Quicktime"); #else /* libquicktime */ if (!G.scene->r.qtcodecdata) G.scene->r.qtcodecdata = MEM_callocN(sizeof(QtCodecData), "QtCodecData"); diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index 1d3a24c4f3b..18d4c0ec1bf 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -2107,12 +2107,17 @@ Scene *copy_scene(Scene *sce, int level) if (sce->r.avicodecdata) { scen->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata); - scen->r.avicodecdata->lpFormat = MEM_dupallocN(scen->r.avicodecdata->lpFormat); - scen->r.avicodecdata->lpParms = MEM_dupallocN(scen->r.avicodecdata->lpParms); } + // make a private copy of the qtcodecdata + + if (sce->r.qtcodecdata) { + + scen->r.qtcodecdata = MEM_dupallocN(sce->r.qtcodecdata); + scen->r.qtcodecdata->cdParms = MEM_dupallocN(scen->r.qtcodecdata->cdParms); + } return scen; } @@ -2210,6 +2215,12 @@ void do_info_buttons(unsigned short event) sce->r.avicodecdata->lpParms = MEM_dupallocN(G.scene->r.avicodecdata->lpParms); } #endif +#ifdef WITH_QUICKTIME + if (sce->r.qtcodecdata) { + sce->r.qtcodecdata = MEM_dupallocN(G.scene->r.qtcodecdata); + sce->r.qtcodecdata->cdParms = MEM_dupallocN(G.scene->r.qtcodecdata->cdParms); + } +#endif } else sce= copy_scene(G.scene, nr-2); |