Browse Source

Merge pull request #62538 from Calinou/movie-writer-split-pngwav

Split MovieWriterPNGWAV into its own file
Rémi Verschelde 3 years ago
parent
commit
ce6c4ab86a

+ 0 - 137
servers/movie_writer/movie_writer.cpp

@@ -30,7 +30,6 @@
 
 #include "movie_writer.h"
 #include "core/config/project_settings.h"
-#include "core/io/dir_access.h"
 
 MovieWriter *MovieWriter::writers[MovieWriter::MAX_WRITERS];
 uint32_t MovieWriter::writer_count = 0;
@@ -170,139 +169,3 @@ void MovieWriter::add_frame(const Ref<Image> &p_image) {
 void MovieWriter::end() {
 	write_end();
 }
-/////////////////////////////////////////
-
-uint32_t MovieWriterPNGWAV::get_audio_mix_rate() const {
-	return mix_rate;
-}
-AudioServer::SpeakerMode MovieWriterPNGWAV::get_audio_speaker_mode() const {
-	return speaker_mode;
-}
-
-void MovieWriterPNGWAV::get_supported_extensions(List<String> *r_extensions) const {
-	r_extensions->push_back("png");
-}
-
-bool MovieWriterPNGWAV::handles_file(const String &p_path) const {
-	return p_path.get_extension().to_lower() == "png";
-}
-
-String MovieWriterPNGWAV::zeros_str(uint32_t p_index) {
-	char zeros[MAX_TRAILING_ZEROS + 1];
-	for (uint32_t i = 0; i < MAX_TRAILING_ZEROS; i++) {
-		uint32_t idx = MAX_TRAILING_ZEROS - i - 1;
-		uint32_t digit = (p_index / uint32_t(Math::pow(double(10), double(idx)))) % 10;
-		zeros[i] = '0' + digit;
-	}
-	zeros[MAX_TRAILING_ZEROS] = 0;
-	return zeros;
-}
-
-Error MovieWriterPNGWAV::write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) {
-	// Quick & Dirty PNGWAV Code based on - https://docs.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference
-
-	base_path = p_base_path.get_basename();
-	if (base_path.is_relative_path()) {
-		base_path = "res://" + base_path;
-	}
-
-	{
-		//Remove existing files before writing anew
-		uint32_t idx = 0;
-		Ref<DirAccess> d = DirAccess::open(base_path.get_base_dir());
-		String file = base_path.get_file();
-		while (true) {
-			String path = file + zeros_str(idx) + ".png";
-			if (d->remove(path) != OK) {
-				break;
-			}
-		}
-	}
-
-	f_wav = FileAccess::open(base_path + ".wav", FileAccess::WRITE_READ);
-	ERR_FAIL_COND_V(f_wav.is_null(), ERR_CANT_OPEN);
-
-	fps = p_fps;
-
-	f_wav->store_buffer((const uint8_t *)"RIFF", 4);
-	int total_size = 4 /* WAVE */ + 8 /* fmt+size */ + 16 /* format */ + 8 /* data+size */;
-	f_wav->store_32(total_size); //will store final later
-	f_wav->store_buffer((const uint8_t *)"WAVE", 4);
-
-	/* FORMAT CHUNK */
-
-	f_wav->store_buffer((const uint8_t *)"fmt ", 4);
-
-	uint32_t channels = 2;
-	switch (speaker_mode) {
-		case AudioServer::SPEAKER_MODE_STEREO:
-			channels = 2;
-			break;
-		case AudioServer::SPEAKER_SURROUND_31:
-			channels = 4;
-			break;
-		case AudioServer::SPEAKER_SURROUND_51:
-			channels = 6;
-			break;
-		case AudioServer::SPEAKER_SURROUND_71:
-			channels = 8;
-			break;
-	}
-
-	f_wav->store_32(16); //standard format, no extra fields
-	f_wav->store_16(1); // compression code, standard PCM
-	f_wav->store_16(channels); //CHANNELS: 2
-
-	f_wav->store_32(mix_rate);
-
-	/* useless stuff the format asks for */
-
-	int bits_per_sample = 32;
-	int blockalign = bits_per_sample / 8 * channels;
-	int bytes_per_sec = mix_rate * blockalign;
-
-	audio_block_size = (mix_rate / fps) * blockalign;
-
-	f_wav->store_32(bytes_per_sec);
-	f_wav->store_16(blockalign); // block align (unused)
-	f_wav->store_16(bits_per_sample);
-
-	/* DATA CHUNK */
-
-	f_wav->store_buffer((const uint8_t *)"data", 4);
-
-	f_wav->store_32(0); //data size... wooh
-	wav_data_size_pos = f_wav->get_position();
-
-	return OK;
-}
-
-Error MovieWriterPNGWAV::write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) {
-	ERR_FAIL_COND_V(!f_wav.is_valid(), ERR_UNCONFIGURED);
-
-	Vector<uint8_t> png_buffer = p_image->save_png_to_buffer();
-
-	Ref<FileAccess> fi = FileAccess::open(base_path + zeros_str(frame_count) + ".png", FileAccess::WRITE);
-	fi->store_buffer(png_buffer.ptr(), png_buffer.size());
-	f_wav->store_buffer((const uint8_t *)p_audio_data, audio_block_size);
-
-	frame_count++;
-
-	return OK;
-}
-
-void MovieWriterPNGWAV::write_end() {
-	if (f_wav.is_valid()) {
-		uint32_t total_size = 4 /* WAVE */ + 8 /* fmt+size */ + 16 /* format */ + 8 /* data+size */;
-		uint32_t datasize = f_wav->get_position() - wav_data_size_pos;
-		f_wav->seek(4);
-		f_wav->store_32(total_size + datasize);
-		f_wav->seek(0x28);
-		f_wav->store_32(datasize);
-	}
-}
-
-MovieWriterPNGWAV::MovieWriterPNGWAV() {
-	mix_rate = GLOBAL_GET("editor/movie_writer/mix_rate");
-	speaker_mode = AudioServer::SpeakerMode(int(GLOBAL_GET("editor/movie_writer/speaker_mode")));
-}

+ 1 - 36
servers/movie_writer/movie_writer.h

@@ -85,39 +85,4 @@ public:
 	void end();
 };
 
-class MovieWriterPNGWAV : public MovieWriter {
-	GDCLASS(MovieWriterPNGWAV, MovieWriter)
-
-	enum {
-		MAX_TRAILING_ZEROS = 8 // more than 10 days at 60fps, no hard drive can put up with this anyway :)
-	};
-
-	uint32_t mix_rate = 48000;
-	AudioServer::SpeakerMode speaker_mode = AudioServer::SPEAKER_MODE_STEREO;
-	String base_path;
-	uint32_t frame_count = 0;
-	uint32_t fps = 0;
-
-	uint32_t audio_block_size = 0;
-
-	Ref<FileAccess> f_wav;
-	uint32_t wav_data_size_pos = 0;
-
-	String zeros_str(uint32_t p_index);
-
-protected:
-	virtual uint32_t get_audio_mix_rate() const override;
-	virtual AudioServer::SpeakerMode get_audio_speaker_mode() const override;
-	virtual void get_supported_extensions(List<String> *r_extensions) const override;
-
-	virtual Error write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) override;
-	virtual Error write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) override;
-	virtual void write_end() override;
-
-	virtual bool handles_file(const String &p_path) const override;
-
-public:
-	MovieWriterPNGWAV();
-};
-
-#endif // VIDEO_WRITER_H
+#endif // MOVIE_WRITER_H

+ 1 - 1
servers/movie_writer/movie_writer_mjpeg.h

@@ -70,4 +70,4 @@ public:
 	MovieWriterMJPEG();
 };
 
-#endif // MOVIE_WRITER_AVIJPEG_H
+#endif // MOVIE_WRITER_MJPEG_H

+ 168 - 0
servers/movie_writer/movie_writer_pngwav.cpp

@@ -0,0 +1,168 @@
+/*************************************************************************/
+/*  movie_writer_pngwav.cpp                                              */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "movie_writer_pngwav.h"
+#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+
+uint32_t MovieWriterPNGWAV::get_audio_mix_rate() const {
+	return mix_rate;
+}
+AudioServer::SpeakerMode MovieWriterPNGWAV::get_audio_speaker_mode() const {
+	return speaker_mode;
+}
+
+void MovieWriterPNGWAV::get_supported_extensions(List<String> *r_extensions) const {
+	r_extensions->push_back("png");
+}
+
+bool MovieWriterPNGWAV::handles_file(const String &p_path) const {
+	return p_path.get_extension().to_lower() == "png";
+}
+
+String MovieWriterPNGWAV::zeros_str(uint32_t p_index) {
+	char zeros[MAX_TRAILING_ZEROS + 1];
+	for (uint32_t i = 0; i < MAX_TRAILING_ZEROS; i++) {
+		uint32_t idx = MAX_TRAILING_ZEROS - i - 1;
+		uint32_t digit = (p_index / uint32_t(Math::pow(double(10), double(idx)))) % 10;
+		zeros[i] = '0' + digit;
+	}
+	zeros[MAX_TRAILING_ZEROS] = 0;
+	return zeros;
+}
+
+Error MovieWriterPNGWAV::write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) {
+	// Quick & Dirty PNGWAV Code based on - https://docs.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference
+
+	base_path = p_base_path.get_basename();
+	if (base_path.is_relative_path()) {
+		base_path = "res://" + base_path;
+	}
+
+	{
+		//Remove existing files before writing anew
+		uint32_t idx = 0;
+		Ref<DirAccess> d = DirAccess::open(base_path.get_base_dir());
+		String file = base_path.get_file();
+		while (true) {
+			String path = file + zeros_str(idx) + ".png";
+			if (d->remove(path) != OK) {
+				break;
+			}
+		}
+	}
+
+	f_wav = FileAccess::open(base_path + ".wav", FileAccess::WRITE_READ);
+	ERR_FAIL_COND_V(f_wav.is_null(), ERR_CANT_OPEN);
+
+	fps = p_fps;
+
+	f_wav->store_buffer((const uint8_t *)"RIFF", 4);
+	int total_size = 4 /* WAVE */ + 8 /* fmt+size */ + 16 /* format */ + 8 /* data+size */;
+	f_wav->store_32(total_size); //will store final later
+	f_wav->store_buffer((const uint8_t *)"WAVE", 4);
+
+	/* FORMAT CHUNK */
+
+	f_wav->store_buffer((const uint8_t *)"fmt ", 4);
+
+	uint32_t channels = 2;
+	switch (speaker_mode) {
+		case AudioServer::SPEAKER_MODE_STEREO:
+			channels = 2;
+			break;
+		case AudioServer::SPEAKER_SURROUND_31:
+			channels = 4;
+			break;
+		case AudioServer::SPEAKER_SURROUND_51:
+			channels = 6;
+			break;
+		case AudioServer::SPEAKER_SURROUND_71:
+			channels = 8;
+			break;
+	}
+
+	f_wav->store_32(16); //standard format, no extra fields
+	f_wav->store_16(1); // compression code, standard PCM
+	f_wav->store_16(channels); //CHANNELS: 2
+
+	f_wav->store_32(mix_rate);
+
+	/* useless stuff the format asks for */
+
+	int bits_per_sample = 32;
+	int blockalign = bits_per_sample / 8 * channels;
+	int bytes_per_sec = mix_rate * blockalign;
+
+	audio_block_size = (mix_rate / fps) * blockalign;
+
+	f_wav->store_32(bytes_per_sec);
+	f_wav->store_16(blockalign); // block align (unused)
+	f_wav->store_16(bits_per_sample);
+
+	/* DATA CHUNK */
+
+	f_wav->store_buffer((const uint8_t *)"data", 4);
+
+	f_wav->store_32(0); //data size... wooh
+	wav_data_size_pos = f_wav->get_position();
+
+	return OK;
+}
+
+Error MovieWriterPNGWAV::write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) {
+	ERR_FAIL_COND_V(!f_wav.is_valid(), ERR_UNCONFIGURED);
+
+	Vector<uint8_t> png_buffer = p_image->save_png_to_buffer();
+
+	Ref<FileAccess> fi = FileAccess::open(base_path + zeros_str(frame_count) + ".png", FileAccess::WRITE);
+	fi->store_buffer(png_buffer.ptr(), png_buffer.size());
+	f_wav->store_buffer((const uint8_t *)p_audio_data, audio_block_size);
+
+	frame_count++;
+
+	return OK;
+}
+
+void MovieWriterPNGWAV::write_end() {
+	if (f_wav.is_valid()) {
+		uint32_t total_size = 4 /* WAVE */ + 8 /* fmt+size */ + 16 /* format */ + 8 /* data+size */;
+		uint32_t datasize = f_wav->get_position() - wav_data_size_pos;
+		f_wav->seek(4);
+		f_wav->store_32(total_size + datasize);
+		f_wav->seek(0x28);
+		f_wav->store_32(datasize);
+	}
+}
+
+MovieWriterPNGWAV::MovieWriterPNGWAV() {
+	mix_rate = GLOBAL_GET("editor/movie_writer/mix_rate");
+	speaker_mode = AudioServer::SpeakerMode(int(GLOBAL_GET("editor/movie_writer/speaker_mode")));
+}

+ 71 - 0
servers/movie_writer/movie_writer_pngwav.h

@@ -0,0 +1,71 @@
+/*************************************************************************/
+/*  movie_writer_pngwav.h                                                */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef MOVIE_WRITER_PNGWAV_H
+#define MOVIE_WRITER_PNGWAV_H
+
+#include "servers/movie_writer/movie_writer.h"
+
+class MovieWriterPNGWAV : public MovieWriter {
+	GDCLASS(MovieWriterPNGWAV, MovieWriter)
+
+	enum {
+		MAX_TRAILING_ZEROS = 8 // more than 10 days at 60fps, no hard drive can put up with this anyway :)
+	};
+
+	uint32_t mix_rate = 48000;
+	AudioServer::SpeakerMode speaker_mode = AudioServer::SPEAKER_MODE_STEREO;
+	String base_path;
+	uint32_t frame_count = 0;
+	uint32_t fps = 0;
+
+	uint32_t audio_block_size = 0;
+
+	Ref<FileAccess> f_wav;
+	uint32_t wav_data_size_pos = 0;
+
+	String zeros_str(uint32_t p_index);
+
+protected:
+	virtual uint32_t get_audio_mix_rate() const override;
+	virtual AudioServer::SpeakerMode get_audio_speaker_mode() const override;
+	virtual void get_supported_extensions(List<String> *r_extensions) const override;
+
+	virtual Error write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) override;
+	virtual Error write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) override;
+	virtual void write_end() override;
+
+	virtual bool handles_file(const String &p_path) const override;
+
+public:
+	MovieWriterPNGWAV();
+};
+
+#endif // MOVIE_WRITER_PNGWAV_H

+ 1 - 0
servers/register_server_types.cpp

@@ -59,6 +59,7 @@
 #include "display_server.h"
 #include "movie_writer/movie_writer.h"
 #include "movie_writer/movie_writer_mjpeg.h"
+#include "movie_writer/movie_writer_pngwav.h"
 #include "navigation_server_2d.h"
 #include "navigation_server_3d.h"
 #include "physics_2d/godot_physics_server_2d.h"