Fix T44122, rendering OpenGL preview movie with audio has wrong audio
authorAntony Riakiotakis <kalast@gmail.com>
Thu, 26 Mar 2015 13:49:59 +0000 (14:49 +0100)
committerAntony Riakiotakis <kalast@gmail.com>
Thu, 26 Mar 2015 13:50:18 +0000 (14:50 +0100)
range and extra frames.

Issue here is that the movie backend would unconditionally use the start
frame of the scene instead of the preview frame. Solved by passing an
explicit "preview" argument.

Strictly speaking, the preview argument is part of the renderdata
struct, that is also passed to the code, but when rendering the final
result we want to unconditionally render the full range regardless of
the preview setting of the render structure.

However, OpenGL rendering does use the preview range so we need to
account for that when making those exports.

This is also a nice chance to correct the filenames, which still used
the full range.

source/blender/blenkernel/BKE_writeavi.h
source/blender/blenkernel/BKE_writeffmpeg.h
source/blender/blenkernel/BKE_writeframeserver.h
source/blender/blenkernel/intern/writeavi.c
source/blender/blenkernel/intern/writeffmpeg.c
source/blender/blenkernel/intern/writeframeserver.c
source/blender/editors/render/render_opengl.c
source/blender/editors/screen/screendump.c
source/blender/quicktime/apple/qtkit_export.m
source/blender/quicktime/quicktime_export.h
source/blender/render/intern/source/pipeline.c

index 78875951ca4957ae01dfd7909c41b4e2973d33fc..8206c36b8953cce0b59ddcdfe7d66e83a78f2be4 100644 (file)
@@ -43,12 +43,12 @@ struct ReportList;
 struct Scene;
 
 typedef struct bMovieHandle {
-       int (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);
+       int (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview);
        int (*append_movie)(struct RenderData *rd, int start_frame, int frame, int *pixels,
                            int rectx, int recty, struct ReportList *reports);
        void (*end_movie)(void);
        int (*get_next_frame)(struct RenderData *rd, struct ReportList *reports); /* optional */
-       void (*get_movie_path)(char *string, struct RenderData *rd); /* optional */
+       void (*get_movie_path)(char *string, struct RenderData *rd, bool preview); /* optional */
 } bMovieHandle;
 
 bMovieHandle *BKE_movie_handle_get(const char imtype);
index 703e84b37980bdab5d7801dfd16e0cebb8057f77..ba6360964d6b088544f8dbb8798cb958a98e9f70 100644 (file)
@@ -69,11 +69,11 @@ struct RenderData;
 struct ReportList;
 struct Scene;
 
-int BKE_ffmpeg_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);
+int BKE_ffmpeg_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview);
 void BKE_ffmpeg_end(void);
 int BKE_ffmpeg_append(struct RenderData *rd, int start_frame, int frame, int *pixels,
                       int rectx, int recty, struct ReportList *reports);
-void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd);
+void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd, bool preview);
 
 void BKE_ffmpeg_preset_set(struct RenderData *rd, int preset);
 void BKE_ffmpeg_image_type_verify(struct RenderData *rd, struct ImageFormatData *imf);
index bdce9abe8ad7da40f938a156be326a1721f415dc..b7d601ea7695a18ba8656abc43a1927fa85662bc 100644 (file)
@@ -40,7 +40,7 @@ struct RenderData;
 struct ReportList;
 struct Scene;
 
-int BKE_frameserver_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);
+int BKE_frameserver_start(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview);
 void BKE_frameserver_end(void);
 int BKE_frameserver_append(struct RenderData *rd, int start_frame, int frame, int *pixels,
                            int rectx, int recty, struct ReportList *reports);
index 85eac1f21edfa5173a729c0fb0e6f07160441c9d..b0e23b6b6033bc45247793ca654d2efbab74b7b4 100644 (file)
@@ -51,7 +51,7 @@
 /* ********************** general blender movie support ***************************** */
 
 static int start_stub(Scene *UNUSED(scene), RenderData *UNUSED(rd), int UNUSED(rectx), int UNUSED(recty),
-                      ReportList *UNUSED(reports))
+                      ReportList *UNUSED(reports), bool UNUSED(preview))
 { return 0; }
 
 static void end_stub(void)
@@ -65,11 +65,11 @@ static int append_stub(RenderData *UNUSED(rd), int UNUSED(start_frame), int UNUS
 #  include "AVI_avi.h"
 
 /* callbacks */
-static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports);
+static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview);
 static void end_avi(void);
 static int append_avi(RenderData *rd, int start_frame, int frame, int *pixels,
                       int rectx, int recty, ReportList *reports);
-static void filepath_avi(char *string, RenderData *rd);
+static void filepath_avi(char *string, RenderData *rd, bool preview);
 #endif  /* WITH_AVI */
 
 #ifdef WITH_QUICKTIME
@@ -129,9 +129,7 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
 #endif
 
        /* in case all above are disabled */
-       (void)imtype;
-
-       return &mh;
+       (void)imtype;return &mh;
 }
 
 /* ****************************************************************** */
@@ -141,10 +139,21 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
 
 static AviMovie *avi = NULL;
 
-static void filepath_avi(char *string, RenderData *rd)
+static void filepath_avi(char *string, RenderData *rd, bool preview)
 {
+       int sfra, efra;
+
        if (string == NULL) return;
 
+       if (preview) {
+               sfra = rd->psfra;
+               efra = rd->pefra;
+       }
+       else {
+               sfra = rd->sfra;
+               efra = rd->efra;
+       }
+
        strcpy(string, rd->pic);
        BLI_path_abs(string, G.main->name);
 
@@ -152,18 +161,18 @@ static void filepath_avi(char *string, RenderData *rd)
 
        if (rd->scemode & R_EXTENSION) {
                if (!BLI_testextensie(string, ".avi")) {
-                       BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+                       BLI_path_frame_range(string, sfra, efra, 4);
                        strcat(string, ".avi");
                }
        }
        else {
                if (BLI_path_frame_check_chars(string)) {
-                       BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+                       BLI_path_frame_range(string, sfra, efra, 4);
                }
        }
 }
 
-static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports)
+static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview)
 {
        int x, y;
        char name[256];
@@ -173,7 +182,7 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL
        
        (void)scene; /* unused */
        
-       filepath_avi(name, rd);
+       filepath_avi(name, rd, preview);
 
        x = rectx;
        y = recty;
@@ -258,7 +267,7 @@ void BKE_movie_filepath_get(char *string, RenderData *rd)
 {
        bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype);
        if (mh->get_movie_path)
-               mh->get_movie_path(string, rd);
+               mh->get_movie_path(string, rd, false);
        else
                string[0] = '\0';
 }
index 57a4927e1490bc2de4f5d67db8fd097f280ff81f..0717369cde8474818df746ae80ede4661a9e6079 100644 (file)
@@ -69,6 +69,7 @@ static int ffmpeg_audio_bitrate = 128;
 static int ffmpeg_gop_size = 12;
 static int ffmpeg_autosplit = 0;
 static int ffmpeg_autosplit_count = 0;
+static bool ffmpeg_preview = false;
 
 static AVFormatContext *outfile = 0;
 static AVStream *video_stream = 0;
@@ -816,7 +817,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
        ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT;
        
        /* Determine the correct filename */
-       BKE_ffmpeg_filepath_get(name, rd);
+       BKE_ffmpeg_filepath_get(name, rd, ffmpeg_preview);
        PRINT("Starting output to %s(ffmpeg)...\n"
                "  Using type=%d, codec=%d, audio_codec=%d,\n"
                "  video_bitrate=%d, audio_bitrate=%d,\n"
@@ -1028,15 +1029,25 @@ static void flush_ffmpeg(void)
  * ********************************************************************** */
 
 /* Get the output filename-- similar to the other output formats */
-void BKE_ffmpeg_filepath_get(char *string, RenderData *rd)
+void BKE_ffmpeg_filepath_get(char *string, RenderData *rd, bool preview)
 {
        char autosplit[20];
 
        const char **exts = get_file_extensions(rd->ffcodecdata.type);
        const char **fe = exts;
+       int sfra, efra;
 
        if (!string || !exts) return;
 
+       if (preview) {
+               sfra = rd->psfra;
+               efra = rd->pefra;
+       }
+       else {
+               sfra = rd->sfra;
+               efra = rd->efra;
+       }
+
        strcpy(string, rd->pic);
        BLI_path_abs(string, G.main->name);
 
@@ -1059,7 +1070,7 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd)
                if (*fe == NULL) {
                        strcat(string, autosplit);
 
-                       BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+                       BLI_path_frame_range(string, sfra, efra, 4);
                        strcat(string, *exts);
                }
                else {
@@ -1070,18 +1081,19 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd)
        }
        else {
                if (BLI_path_frame_check_chars(string)) {
-                       BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+                       BLI_path_frame_range(string, sfra, efra, 4);
                }
 
                strcat(string, autosplit);
        }
 }
 
-int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports)
+int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview)
 {
        int success;
 
        ffmpeg_autosplit_count = 0;
+       ffmpeg_preview = preview;
 
        success = start_ffmpeg_impl(rd, rectx, recty, reports);
 #ifdef WITH_AUDASPACE
@@ -1111,7 +1123,7 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty,
                }
 
                specs.rate = rd->ffcodecdata.audio_mixrate;
-               audio_mixdown_device = BKE_sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume);
+               audio_mixdown_device = BKE_sound_mixdown(scene, specs, preview ? rd->psfra : rd->sfra, rd->ffcodecdata.audio_volume);
 #ifdef FFMPEG_CODEC_TIME_BASE
                c->time_base.den = specs.rate;
                c->time_base.num = 1;
@@ -1162,7 +1174,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i
        }
 
 #ifdef WITH_AUDASPACE
-       write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
+       write_audio_frames((frame - start_frame) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
 #endif
        return success;
 }
index ae6b19fb0192f1354a0b1bc02e353bdede1c58fc..9cac86d62bd7646854e7284b0224afe995c85859 100644 (file)
@@ -110,7 +110,7 @@ static int closesocket(int fd)
 }
 #endif
 
-int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports)
+int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx, int recty, ReportList *reports, bool UNUSED(preview))
 {
        struct sockaddr_in addr;
        int arg = 1;
index d8da0e9bcda8a5d2688f1000b9106c37daa1ab20..5c8bee07420896c337429beaab70851788b63074 100644 (file)
@@ -556,7 +556,7 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
        oglrender->reports = op->reports;
        oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype);
        if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
-               if (!oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey, oglrender->reports)) {
+               if (!oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey, oglrender->reports, PRVRANGEON != 0)) {
                        screen_opengl_render_end(C, oglrender);
                        return 0;
                }
index 9c05f1d4780b3bf490a95ac9fb0035d31e1feb94..330bc7e3395f71ee72f0f4ae1bada9528f7256a4 100644 (file)
@@ -344,7 +344,7 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
        rd.frs_sec_base = 1.0f;
        
        if (BKE_imtype_is_movie(rd.im_format.imtype)) {
-               if (!mh->start_movie(sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports)) {
+               if (!mh->start_movie(sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports, false)) {
                        printf("screencast job stopped\n");
                        return;
                }
index cbc76e26aa9ee8c2b10ca0d225b3a2d32f5544d5..4214fa9ac32ad563a1d41a4555a3a0d4d1ab9ade 100644 (file)
@@ -219,10 +219,21 @@ static NSString *stringWithCodecType(int codecType)
        return [NSString stringWithCString:str encoding:NSASCIIStringEncoding];
 }
 
-void makeqtstring(RenderData *rd, char *string)
+void makeqtstring(RenderData *rd, char *string, bool preview)
 {
+       int sfra, efra;
+
        char txt[64];
 
+       if (preview) {
+               sfra = rd->psfra;
+               efra = rd->pefra;
+       }
+       else {
+               sfra = rd->sfra;
+               efra = rd->efra;
+       }
+       
        strcpy(string, rd->pic);
        BLI_path_abs(string, G.main->name);
 
@@ -234,10 +245,21 @@ void makeqtstring(RenderData *rd, char *string)
        }
 }
 
-void filepath_qt(char *string, RenderData *rd)
+void filepath_qt(char *string, RenderData *rd, bool preview)
 {
+       int sfra, efra;
+
        if (string == NULL) return;
        
+       if (preview) {
+               sfra = rd->psfra;
+               efra = rd->pefra;
+       }
+       else {
+               sfra = rd->sfra;
+               efra = rd->efra;
+       }
+
        strcpy(string, rd->pic);
        BLI_path_abs(string, G.main->name);
        
@@ -245,13 +267,13 @@ void filepath_qt(char *string, RenderData *rd)
 
        if (rd->scemode & R_EXTENSION) {
                if (!BLI_testextensie(string, ".mov")) {
-                       BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+                       BLI_path_frame_range(string, sfra, efra, 4);
                        strcat(string, ".mov");
                }
        }
        else {
                if (BLI_path_frame_check_chars(string)) {
-                       BLI_path_frame_range(string, rd->sfra, rd->efra, 4);
+                       BLI_path_frame_range(string, sfra, efra, 4);
                }
        }
 }
@@ -312,16 +334,26 @@ static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter,
 
 #pragma mark export functions
 
-int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports)
+int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports, bool preview)
 {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSError *error;
        char name[1024];
        int success = 1;
        OSStatus err = noErr;
+       int sfra, efra;
 
        if (qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport");
        
+       if (preview) {
+               sfra = rd->psfra;
+               efra = rd->pefra;
+       }
+       else {
+               sfra = rd->sfra;
+               efra = rd->efra;
+       }
+       
        [QTMovie enterQTKitOnThread];
        
        /* Check first if the QuickTime 7.2.1 initToWritableFile: method is available */
@@ -330,7 +362,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
                success = 0;
        }
        else {
-               makeqtstring(rd, name);
+               makeqtstring(rd, name, preview);
                qtexport->filename = [[NSString alloc] initWithCString:name
                                                                       encoding:[NSString defaultCStringEncoding]];
                qtexport->movie = nil;
@@ -591,13 +623,13 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
                                specs.format = U.audioformat;
                                specs.rate = U.audiorate;
                                qtexport->audioInputDevice = AUD_openReadDevice(specs);
-                               AUD_playDevice(qtexport->audioInputDevice, scene->sound_scene, rd->sfra * rd->frs_sec_base / rd->frs_sec);
+                               AUD_playDevice(qtexport->audioInputDevice, scene->sound_scene, sfra * rd->frs_sec_base / rd->frs_sec);
 
                                qtexport->audioOutputPktPos = 0;
                                qtexport->audioTotalExportedFrames = 0;
                                qtexport->audioTotalSavedFrames = 0;
                                
-                               qtexport->audioLastFrame = (rd->efra - rd->sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec;
+                               qtexport->audioLastFrame = (efra - sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec;
                        }
                }
        }
@@ -654,7 +686,7 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in
                UInt32 audioPacketsConverted;
 
                // Upper limit on total exported audio frames for this particular video frame
-               const UInt64 exportedAudioFrameLimit = (frame - rd->sfra) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec;
+               const UInt64 exportedAudioFrameLimit = (frame - start_frame) * qtexport->audioInputFormat.mSampleRate * rd->frs_sec_base / rd->frs_sec;
 
                /* Append audio */
                while (qtexport->audioTotalExportedFrames < exportedAudioFrameLimit) {
index a499cd462b775dd45d01805332e2c03ac6b0bfe1..6709f87fb1cd99e9e99e2dc1ade728ada4c3733d 100644 (file)
@@ -56,10 +56,10 @@ struct ReportList;
 struct Scene;
 struct wmOperatorType;
 
-int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports);    //for movie handle (BKE writeavi.c now)
+int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview);      //for movie handle (BKE writeavi.c now)
 int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, struct ReportList *reports);
 void end_qt(void);
-void filepath_qt(char *string, struct RenderData *rd);
+void filepath_qt(char *string, struct RenderData *rd, bool preview);
 
 /*RNA helper functions */
 void quicktime_verify_image_type(struct RenderData *rd, struct ImageFormatData *imf); //used by RNA for defaults values init, if needed
@@ -76,7 +76,7 @@ int quicktime_rnatmpvalue_from_audiocodectype(int codecType);
 int quicktime_audiocodecType_from_rnatmpvalue(int rnatmpvalue);
 
 void free_qtcomponentdata(void);
-void makeqtstring(struct RenderData *rd, char *string);                //for playanim.c
+void makeqtstring(struct RenderData *rd, char *string, bool preview);          //for playanim.c
 
 
 
index b397db7c31b2f9758e2de47d3019cb00545479a2..fe51696b16c94073e33aed6dcdbde23039d48627 100644 (file)
@@ -3025,7 +3025,8 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
                        height = re->recty;
                }
 
-               if (!mh->start_movie(scene, &re->r, width, height, re->reports))
+               /* last argument here depends on users really, but no users using preview have been found so far */
+               if (!mh->start_movie(scene, &re->r, width, height, re->reports, false))
                        G.is_break = true;
        }