diff --git a/release/scripts/ui/properties_render.py b/release/scripts/ui/properties_render.py index 42faa00fe00..f5aeef70644 100644 --- a/release/scripts/ui/properties_render.py +++ b/release/scripts/ui/properties_render.py @@ -337,6 +337,31 @@ class RENDER_PT_output(RenderButtonsPanel): split.itemR(rd, "tiff_bit") +class RENDER_PT_QTencoding(RenderButtonsPanel): + bl_label = "Encoding" + bl_default_closed = True + COMPAT_ENGINES = set(['BLENDER_RENDER']) + + def poll(self, context): + rd = context.scene.render_data + return rd.file_format in ('QUICKTIME_QTKIT') # QUICKTIME will be added later + + def draw(self, context): + layout = self.layout + + rd = context.scene.render_data + wide_ui = context.region.width > narrowui + + split = layout.split() + + split.itemR(rd, "quicktime_codec_type") + + split = layout.split() + + if rd.file_format == 'QUICKTIME_QTKIT': + split.itemR(rd, "quicktime_codec_spatial_quality", text="Quality") + + class RENDER_PT_encoding(RenderButtonsPanel): bl_label = "Encoding" bl_default_closed = True @@ -516,6 +541,7 @@ bpy.types.register(RENDER_PT_dimensions) bpy.types.register(RENDER_PT_antialiasing) bpy.types.register(RENDER_PT_shading) bpy.types.register(RENDER_PT_output) +bpy.types.register(RENDER_PT_QTencoding) bpy.types.register(RENDER_PT_encoding) bpy.types.register(RENDER_PT_performance) bpy.types.register(RENDER_PT_post_processing) diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index d4c8aead513..e998b943a2e 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -77,7 +77,7 @@ typedef struct AviCodecData { } AviCodecData; typedef struct QuicktimeCodecData { - + /*Old quicktime implementation compatibility fields, read only in 2.5 - deprecated*/ void *cdParms; /* codec/compressor options */ void *pad; /* padding */ @@ -86,6 +86,22 @@ typedef struct QuicktimeCodecData { char qtcodecname[128]; } QuicktimeCodecData; + +typedef struct QuicktimeCodecSettings { + /* Codec settings detailed for 2.5 implementation*/ + int codecType; /* Types defined in quicktime_export.h */ + int codecSpatialQuality; /* in 0-100 scale, to be translated in 0-1024 for qt use */ + + /* Settings not available in current QTKit API */ + int codec; + int codecFlags; + int colorDepth; + int codecTemporalQuality; /* in 0-100 scale, to be translated in 0-1024 for qt use */ + int minSpatialQuality; /* in 0-100 scale, to be translated in 0-1024 for qt use */ + int minTemporalQuality; /* in 0-100 scale, to be translated in 0-1024 for qt use */ + int keyFrameRate; + int bitRate; /* bitrate in bps */ +} QuicktimeCodecSettings; typedef struct FFMpegCodecData { int type; @@ -176,6 +192,7 @@ typedef struct RenderData { struct AviCodecData *avicodecdata; struct QuicktimeCodecData *qtcodecdata; + struct QuicktimeCodecSettings qtcodecsettings; struct FFMpegCodecData ffcodecdata; int cfra, sfra, efra; /* frames as in 'images' */ diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index 72dc6be683c..4be35a9fe12 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -30,6 +30,7 @@ if env['WITH_BF_OGG']: if env['WITH_BF_QUICKTIME']: defs.append('WITH_QUICKTIME') + incs += ' ../quicktime' if env['WITH_BF_LCMS']: defs.append('WITH_LCMS') diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index c9c02fbecde..113dfc51138 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -63,6 +63,7 @@ IF(WITH_DDS) ENDIF(WITH_DDS) IF(WITH_QUICKTIME) + SET(INC "${INC} ../../quicktime") ADD_DEFINITIONS(-DWITH_QUICKTIME) ENDIF(WITH_QUICKTIME) diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index c63b63ce5f7..e5a08c9aeea 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -52,6 +52,7 @@ if env['WITH_BF_OGG']: if env['WITH_BF_QUICKTIME']: defs.append('WITH_QUICKTIME') + incs += ' ../../quicktime' if env['WITH_BF_LCMS']: defs.append('WITH_LCMS') diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 64a9f8d521f..3acb800dedf 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -35,6 +35,10 @@ /* Include for Bake Options */ #include "RE_pipeline.h" +#ifdef WITH_QUICKTIME +#include "quicktime_export.h" +#endif + #ifdef WITH_FFMPEG #include "BKE_writeffmpeg.h" #include @@ -87,6 +91,7 @@ EnumPropertyItem proportional_editing_items[] = { #include "ED_info.h" #include "ED_node.h" #include "ED_view3d.h" +#include "ED_object.h" #include "RE_pipeline.h" @@ -349,6 +354,9 @@ static void rna_SceneRenderData_file_format_set(PointerRNA *ptr, int value) #ifdef WITH_FFMPEG ffmpeg_verify_image_type(rd); #endif +#ifdef WITH_QUICKTIME + quicktime_verify_image_type(rd); +#endif } void rna_SceneRenderData_jpeg2k_preset_update(RenderData *rd) @@ -1439,7 +1447,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {R_AVICODEC, "AVICODEC", ICON_FILE_MOVIE, "AVI Codec", ""}, #endif #ifdef WITH_QUICKTIME +# ifdef USE_QTKIT + {R_QUICKTIME, "QUICKTIME_QTKIT", ICON_FILE_MOVIE, "QuickTime", ""}, +# else {R_QUICKTIME, "QUICKTIME", ICON_FILE_MOVIE, "QuickTime", ""}, +# endif #endif #ifdef __sgi {R_MOVIE, "MOVIE", ICON_FILE_MOVIE, "Movie", ""}, @@ -1486,6 +1498,23 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {16, "16", 0, "16", "16 bit color channels"}, {0, NULL, 0, NULL, NULL}}; #endif + +#ifdef WITH_QUICKTIME + static EnumPropertyItem quicktime_codec_type_items[] = { + {QT_CODECTYPE_RAW, "RAW", 0, "Uncompressed", ""}, + {QT_CODECTYPE_JPEG, "JPEG", 0, "JPEG", ""}, + {QT_CODECTYPE_MJPEGA, "MJPEG_A", 0, "M-JPEG A", ""}, + {QT_CODECTYPE_MJPEGB, "MJPEG_B", 0, "M-JPEG B", ""}, + {QT_CODECTYPE_DVCPAL, "DVCPAL", 0, "DV PAL", ""}, + {QT_CODECTYPE_DVCNTSC, "DVCNTSC", 0, "DV/DVCPRO NTSC", ""}, + {QT_CODECTYPE_DVCPROHD720p, "DVCPROHD720P", 0, "DVCPRO HD 720p"}, + {QT_CODECTYPE_DVCPROHD1080i50, "DVCPROHD1080I50", 0, "DVCPRO HD 1080i50"}, + {QT_CODECTYPE_DVCPROHD1080i60, "DVCPROHD1080I60", 0, "DVCPRO HD 1080i60"}, + {QT_CODECTYPE_MPEG4, "MPEG4", 0, "MPEG4", ""}, + {QT_CODECTYPE_H263, "H263", 0, "H.263", ""}, + {QT_CODECTYPE_H264, "H264", 0, "H.264", ""}, + {0, NULL, 0, NULL, NULL}}; +#endif #ifdef WITH_FFMPEG static EnumPropertyItem ffmpeg_format_items[] = { @@ -1676,6 +1705,22 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); #endif +#ifdef WITH_QUICKTIME + /* QuickTime */ + + prop= RNA_def_property(srna, "quicktime_codec_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "qtcodecsettings.codecType"); + RNA_def_property_enum_items(prop, quicktime_codec_type_items); + RNA_def_property_ui_text(prop, "Codec", "QuickTime codec type"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "quicktime_codec_spatial_quality", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "qtcodecsettings.codecSpatialQuality"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Spatial quality", "Intra-frame spatial quality level"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); +#endif + #ifdef WITH_FFMPEG /* FFMPEG Video*/ diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m index 460b35a0592..9f2a97dee23 100644 --- a/source/blender/quicktime/apple/qtkit_export.m +++ b/source/blender/quicktime/apple/qtkit_export.m @@ -74,6 +74,37 @@ typedef struct QuicktimeExport { static struct QuicktimeExport *qtexport; +static NSString *stringWithCodecType(int codecType) { + switch (codecType) { + case QT_CODECTYPE_RAW: + return @"raw "; + case QT_CODECTYPE_MJPEGA: + return @"mjpa"; + case QT_CODECTYPE_MJPEGB: + return @"mjpb"; + case QT_CODECTYPE_DVCPAL: + return @"dvcp"; + case QT_CODECTYPE_DVCNTSC: + return @"dvc "; + case QT_CODECTYPE_MPEG4: + return @"mp4v"; + case QT_CODECTYPE_H263: + return @"h263"; + case QT_CODECTYPE_H264: + return @"avc1"; + case QT_CODECTYPE_DVCPROHD720p: + return @"dvhp"; + case QT_CODECTYPE_DVCPROHD1080i50: + return @"dvh5"; + case QT_CODECTYPE_DVCPROHD1080i60: + return @"dvh6"; + + case QT_CODECTYPE_JPEG: + default: + return @"jpeg"; + } +} + void makeqtstring (RenderData *rd, char *string) { char txt[64]; @@ -121,13 +152,22 @@ void start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty) qtexport->frameDuration = QTMakeTime(rd->frs_sec_base*1000, rd->frs_sec*1000); - /* specifying the codec attributes - TODO: get these values from RenderData/scene*/ - qtexport->frameAttributes = [NSDictionary dictionaryWithObjectsAndKeys:@"jpeg", - QTAddImageCodecType, - [NSNumber numberWithLong:codecHighQuality], - QTAddImageCodecQuality, - nil]; + /* specifying the codec attributes : try to retrieve them from render data first*/ + if (rd->qtcodecsettings.codecType) { + qtexport->frameAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + stringWithCodecType(rd->qtcodecsettings.codecType), + QTAddImageCodecType, + [NSNumber numberWithLong:((rd->qtcodecsettings.codecSpatialQuality)*codecLosslessQuality)/100], + QTAddImageCodecQuality, + nil]; + } + else { + qtexport->frameAttributes = [NSDictionary dictionaryWithObjectsAndKeys:@"jpeg", + QTAddImageCodecType, + [NSNumber numberWithLong:codecHighQuality], + QTAddImageCodecQuality, + nil]; + } [qtexport->frameAttributes retain]; } } @@ -206,83 +246,17 @@ void end_qt(void) void free_qtcomponentdata(void) { } - -int get_qtcodec_settings(RenderData *rd) +void quicktime_verify_image_type(RenderData *rd) { -/* - // get previous selected codecsetting, if any - if(rd->qtcodecdata && rd->qtcodecdata->cdParms) { - QT_GetCodecSettingsFromScene(rd); - check_renderbutton_framerate(rd); - } else { - // configure the standard image compression dialog box - // set some default settings - qtdata->gSpatialSettings.codec = anyCodec; - qtdata->gSpatialSettings.spatialQuality = codecMaxQuality; - qtdata->gTemporalSettings.temporalQuality = codecMaxQuality; - qtdata->gTemporalSettings.keyFrameRate = 25; - qtdata->aDataRateSetting.dataRate = 90 * 1024; - - err = SCSetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); - CheckError(err, "SCSetInfo1 error"); - err = SCSetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); - CheckError(err, "SCSetInfo2 error"); - err = SCSetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); - CheckError(err, "SCSetInfo3 error"); - } - - check_renderbutton_framerate(rd); - - // put up the dialog box - it needs to be called from the main thread - err = SCRequestSequenceSettings(qtdata->theComponent); - - if (err == scUserCancelled) { - G.afbreek = 1; - return 0; - } - - // get user selected data - SCGetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); - SCGetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); - SCGetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); - - QT_SaveCodecSettingsToScene(rd); - - // framerate jugglin' - switch (qtexport->frameRate) { - case 1571553: // 23.98 fps - qtexport->frameDuration = QTMakeTime(1001, 24000); - rd->frs_sec = 24; - rd->frs_sec_base = 1.001; - break; - case 1964113: // 29.97 fps - qtexport->frameDuration = QTMakeTime(1001, 30000); - rd->frs_sec = 30; - rd->frs_sec_base = 1.001; - break; - case 3928227: // 59.94 fps - qtexport->frameDuration = QTMakeTime(1001, 60000); - rd->frs_sec = 60; - rd->frs_sec_base = 1.001; - break; - default: - { - double fps = qtexport->frameRate; - qtexport->frameDuration = QTMakeTime(60000/(qtexport->frameRate / 65536), 60000); + if (rd->imtype == R_QUICKTIME) { + if ((rd->qtcodecsettings.codecType<= 0) || + (rd->qtcodecsettings.codecSpatialQuality <0) || + (rd->qtcodecsettings.codecSpatialQuality > 100)) { - if ((qtexport->frameRate & 0xffff) == 0) { - rd->frs_sec = fps / 65536; - rd->frs_sec_base = 1; - } else { - // we do our very best... - rd->frs_sec = (fps * 10000 / 65536); - rd->frs_sec_base = 10000; - } + rd->qtcodecsettings.codecType = QT_CODECTYPE_JPEG; + rd->qtcodecsettings.codecSpatialQuality = (codecHighQuality*100)/codecLosslessQuality; } - break; } -*/ - return 1; } #endif /* _WIN32 || __APPLE__ */ diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m index 980aa855822..500ee13330d 100644 --- a/source/blender/quicktime/apple/qtkit_import.m +++ b/source/blender/quicktime/apple/qtkit_import.m @@ -157,8 +157,9 @@ static ImBuf * nsImageToiBuf(NSImage *sourceImage, int width, int height) } } - if (([bitmapImage bitmapFormat] & 0x5) == 0) { - /* Try a fast copy if the image is a planar RGBA 32bit bitmap*/ + if (([bitmapImage bitsPerPixel] == 32) && (([bitmapImage bitmapFormat] & 0x5) == 0) + && ![bitmapImage isPlanar]) { + /* Try a fast copy if the image is a meshed RGBA 32bit bitmap*/ toIBuf = (uchar*)ibuf->rect; rasterRGB = (uchar*)[bitmapImage bitmapData]; for (y = 0; y < height; y++) { diff --git a/source/blender/quicktime/apple/quicktime_export.c b/source/blender/quicktime/apple/quicktime_export.c index bec26bbb207..851b3c5b245 100644 --- a/source/blender/quicktime/apple/quicktime_export.c +++ b/source/blender/quicktime/apple/quicktime_export.c @@ -165,8 +165,6 @@ static OSErr QT_SaveCodecSettingsToScene(RenderData *rd) qcd->cdSize = mySize; GetCodecInfo (&ci, qtdata->gSpatialSettings.codecType, 0); - CopyPascalStringToC(ci.typeName, str); - sprintf(qcd->qtcodecname, "Codec: %s", str); } else { printf("Quicktime: QT_SaveCodecSettingsToScene failed\n"); } @@ -599,6 +597,18 @@ static void check_renderbutton_framerate(RenderData *rd) } } +void quicktime_verify_image_type(RenderData *rd) +{ + if (rd->imtype == R_QUICKTIME) { + if ((rd->qtcodecsettings.codecType<= 0) || + (rd->qtcodecsettings.codecSpatialQuality <0) || + (rd->qtcodecsettings.codecSpatialQuality > 100)) { + + rd->qtcodecsettings.codecType = QT_CODECTYPE_JPEG; + rd->qtcodecsettings.codecSpatialQuality = (codecHighQuality*100)/codecLosslessQuality; + } + } +} int get_qtcodec_settings(RenderData *rd) { @@ -623,8 +633,8 @@ int get_qtcodec_settings(RenderData *rd) // set some default settings: codec=jpeg, quality = max qtdata->gSpatialSettings.codecType = kJPEGCodecType; qtdata->gSpatialSettings.codec = anyCodec; - qtdata->gSpatialSettings.spatialQuality = codecMaxQuality; - qtdata->gTemporalSettings.temporalQuality = codecMaxQuality; + qtdata->gSpatialSettings.spatialQuality = codecHighQuality; + qtdata->gTemporalSettings.temporalQuality = codecHighQuality; qtdata->gTemporalSettings.keyFrameRate = 25; qtdata->aDataRateSetting.dataRate = 5 * 1024 * 1024; diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h index 4afcebab7bd..7972c826190 100644 --- a/source/blender/quicktime/quicktime_export.h +++ b/source/blender/quicktime/quicktime_export.h @@ -33,14 +33,30 @@ #define __AIFF__ +/* Quicktime codec types defines */ +#define QT_CODECTYPE_JPEG 1 +#define QT_CODECTYPE_MJPEGA 2 +#define QT_CODECTYPE_MJPEGB 3 +#define QT_CODECTYPE_DVCPAL 4 +#define QT_CODECTYPE_DVCNTSC 5 +#define QT_CODECTYPE_MPEG4 6 +#define QT_CODECTYPE_H263 7 +#define QT_CODECTYPE_H264 8 +#define QT_CODECTYPE_RAW 9 +#define QT_CODECTYPE_DVCPROHD720p 10 +#define QT_CODECTYPE_DVCPROHD1080i50 11 +#define QT_CODECTYPE_DVCPROHD1080i60 12 + // quicktime movie output functions struct RenderData; +struct Scene; void start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty); //for movie handle (BKE writeavi.c now) void append_qt(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); void end_qt(void); -int get_qtcodec_settings(struct RenderData *rd); //for buttons.c +void quicktime_verify_image_type(struct RenderData *rd); //used by RNA for defaults values init, if needed + void free_qtcomponentdata(void); void makeqtstring(struct RenderData *rd, char *string); //for playanim.c