diff --git a/src/AudioReaderSource.cpp b/src/AudioReaderSource.cpp
index acd69deb..19fbb6ca 100644
--- a/src/AudioReaderSource.cpp
+++ b/src/AudioReaderSource.cpp
@@ -35,21 +35,25 @@ using namespace std;
using namespace openshot;
// Constructor that reads samples from a reader
-AudioReaderSource::AudioReaderSource(ReaderBase *audio_reader, int64_t starting_frame_number, int buffer_size)
- : reader(audio_reader), frame_number(starting_frame_number),
- size(buffer_size), position(0), frame_position(0), estimated_frame(0), speed(1) {
-
- // Initialize an audio buffer (based on reader)
- buffer = new juce::AudioSampleBuffer(reader->info.channels, size);
-
- // initialize the audio samples to zero (silence)
+AudioReaderSource::AudioReaderSource(
+ ReaderBase *audio_reader, int64_t starting_frame_number, int buffer_size
+) :
+ position(0),
+ size(buffer_size),
+ buffer(new juce::AudioSampleBuffer(audio_reader->info.channels, buffer_size)),
+ speed(1),
+ reader(audio_reader),
+ frame_number(starting_frame_number),
+ frame_position(0),
+ estimated_frame(0)
+{
+ // Zero the buffer contents
buffer->clear();
}
// Destructor
AudioReaderSource::~AudioReaderSource()
{
- // Clear and delete the buffer
delete buffer;
buffer = NULL;
}
diff --git a/src/ClipBase.h b/src/ClipBase.h
index c38b9790..2f138a5c 100644
--- a/src/ClipBase.h
+++ b/src/ClipBase.h
@@ -68,15 +68,13 @@ namespace openshot {
CacheMemory cache;
/// Constructor for the base clip
- ClipBase() {
- // Initialize values
- position = 0.0;
- layer = 0;
- start = 0.0;
- end = 0.0;
- previous_properties = "";
- timeline = NULL;
- };
+ ClipBase() :
+ position(0.0),
+ layer(0),
+ start(0.0),
+ end(0.0),
+ previous_properties(""),
+ timeline(nullptr) {}
// Compare a clip using the Position() property
bool operator< ( ClipBase& a) { return (Position() < a.Position()); }
diff --git a/src/Color.cpp b/src/Color.cpp
index e848f1f7..c877cbd4 100644
--- a/src/Color.cpp
+++ b/src/Color.cpp
@@ -28,6 +28,8 @@
* along with OpenShot Library. If not, see .
*/
+#include
+
#include "Color.h"
#include "Exceptions.h"
diff --git a/src/Coordinate.cpp b/src/Coordinate.cpp
index 6a4abb21..d2a2ed3c 100644
--- a/src/Coordinate.cpp
+++ b/src/Coordinate.cpp
@@ -34,14 +34,14 @@
using namespace openshot;
// Default constructor for a coordinate, delegating to the full signature
-Coordinate::Coordinate() : Coordinate::Coordinate(0, 0) {};
+Coordinate::Coordinate() : Coordinate::Coordinate(0, 0) {}
// Constructor which also allows the user to set the X and Y
-Coordinate::Coordinate(double x, double y) : X(x), Y(y) {};
+Coordinate::Coordinate(double x, double y) : X(x), Y(y) {}
// Constructor which accepts a std::pair for (X, Y)
Coordinate::Coordinate(const std::pair& co)
- : X(co.first), Y(co.second) {};
+ : X(co.first), Y(co.second) {}
// Generate JSON string of this object
std::string Coordinate::Json() const {
diff --git a/src/Coordinate.h b/src/Coordinate.h
index 0a3ba978..d4576cd2 100644
--- a/src/Coordinate.h
+++ b/src/Coordinate.h
@@ -37,43 +37,57 @@
namespace openshot {
- /**
- * @brief This class represents a Cartesian coordinate (X, Y) used in the Keyframe animation system.
- *
- * Animation involves the changing (i.e. interpolation) of numbers over time. A series of Coordinate
- * objects allows us to plot a specific curve or line used during interpolation. In other words, it helps us
- * control how a number changes over time (quickly or slowly).
- *
- * Please see the following Example Code:
- * \code
- * Coordinate c1(2,4);
- * assert(c1.X == 2.0f);
- * assert(c1.Y == 4.0f);
- * \endcode
- */
- class Coordinate {
- public:
- double X; ///< The X value of the coordinate (usually representing the frame #)
- double Y; ///< The Y value of the coordinate (usually representing the value of the property being animated)
+/**
+ * @brief A Cartesian coordinate (X, Y) used in the Keyframe animation system.
+ *
+ * Animation involves the changing (i.e. interpolation) of numbers over time.
+ * A series of Coordinate objects allows us to plot a specific curve or line
+ * used during interpolation. In other words, it helps us control how a
+ * value changes over time — whether it's increasing or decreasing
+ * (the direction of the slope) and how quickly (the steepness of the curve).
+ *
+ * Please see the following Example Code:
+ * \code
+ * Coordinate c1(2,4);
+ * assert(c1.X == 2.0f);
+ * assert(c1.Y == 4.0f);
+ * \endcode
+ */
+class Coordinate {
+public:
+ double X; ///< The X value of the coordinate (usually representing the frame #)
+ double Y; ///< The Y value of the coordinate (usually representing the value of the property being animated)
- /// The default constructor, which defaults to (0,0)
- Coordinate();
+ /// The default constructor, which defaults to (0,0)
+ Coordinate();
- /// @brief Constructor which also sets the X and Y
- /// @param x The X coordinate (usually representing the frame #)
- /// @param y The Y coordinate (usually representing the value of the property being animated)
- Coordinate(double x, double y);
+ /// @brief Constructor which also sets the X and Y
+ /// @param x The X coordinate (usually representing the frame #)
+ /// @param y The Y coordinate (usually representing the value of the property being animated)
+ Coordinate(double x, double y);
- /// @brief Constructor which accepts a std::pair tuple for {X, Y}
- /// @param co A std::pair tuple containing (X, Y)
- Coordinate(const std::pair& co);
+ /// @brief Constructor which accepts a std::pair tuple for {X, Y}
+ /// @param co A std::pair tuple containing (X, Y)
+ Coordinate(const std::pair& co);
- // Get and Set JSON methods
- std::string Json() const; ///< Generate JSON string of this object
- Json::Value JsonValue() const; ///< Generate Json::Value for this object
- void SetJson(const std::string value); ///< Load JSON string into this object
- void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object
- };
+ // Get and Set JSON methods
+ std::string Json() const; ///< Generate JSON string of this object
+ Json::Value JsonValue() const; ///< Generate Json::Value for this object
+ void SetJson(const std::string value); ///< Load JSON string into this object
+ void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object
+};
+
+/// Stream output operator for openshot::Coordinate
+template
+std::basic_ostream&
+operator<<(std::basic_ostream& o, const openshot::Coordinate& co) {
+ std::basic_ostringstream s;
+ s.flags(o.flags());
+ s.imbue(o.getloc());
+ s.precision(o.precision());
+ s << "(" << co.X << ", " << co.Y << ")";
+ return o << s.str();
+}
}
diff --git a/src/EffectBase.cpp b/src/EffectBase.cpp
index b75a0820..a475c7eb 100644
--- a/src/EffectBase.cpp
+++ b/src/EffectBase.cpp
@@ -28,6 +28,9 @@
* along with OpenShot Library. If not, see .
*/
+#include
+#include
+
#include "EffectBase.h"
#include "Exceptions.h"
@@ -57,16 +60,16 @@ void EffectBase::InitEffectInfo()
}
// Display file information
-void EffectBase::DisplayInfo() {
- std::cout << std::fixed << std::setprecision(2) << std::boolalpha;
- std::cout << "----------------------------" << std::endl;
- std::cout << "----- Effect Information -----" << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "--> Name: " << info.name << std::endl;
- std::cout << "--> Description: " << info.description << std::endl;
- std::cout << "--> Has Video: " << info.has_video << std::endl;
- std::cout << "--> Has Audio: " << info.has_audio << std::endl;
- std::cout << "----------------------------" << std::endl;
+void EffectBase::DisplayInfo(std::ostream* out) {
+ *out << std::fixed << std::setprecision(2) << std::boolalpha;
+ *out << "----------------------------" << std::endl;
+ *out << "----- Effect Information -----" << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "--> Name: " << info.name << std::endl;
+ *out << "--> Description: " << info.description << std::endl;
+ *out << "--> Has Video: " << info.has_video << std::endl;
+ *out << "--> Has Audio: " << info.has_audio << std::endl;
+ *out << "----------------------------" << std::endl;
}
// Constrain a color value from 0 to 255
diff --git a/src/EffectBase.h b/src/EffectBase.h
index dc78a7c9..05936500 100644
--- a/src/EffectBase.h
+++ b/src/EffectBase.h
@@ -87,7 +87,7 @@ namespace openshot
EffectInfoStruct info;
/// Display effect information in the standard output stream (stdout)
- void DisplayInfo();
+ void DisplayInfo(std::ostream* out=&std::cout);
/// Constrain a color value from 0 to 255
int constrain(int color_value);
diff --git a/src/Fraction.cpp b/src/Fraction.cpp
index d4898326..cb13c393 100644
--- a/src/Fraction.cpp
+++ b/src/Fraction.cpp
@@ -34,21 +34,20 @@
using namespace openshot;
// Delegating constructors
-Fraction::Fraction() : Fraction::Fraction(1, 1) {};
+Fraction::Fraction() : Fraction::Fraction(1, 1) {}
Fraction::Fraction(std::pair pair)
- : Fraction::Fraction(pair.first, pair.second) {};
+ : Fraction::Fraction(pair.first, pair.second) {}
Fraction::Fraction(std::map mapping)
- : Fraction::Fraction(mapping["num"], mapping["den"]) {};
+ : Fraction::Fraction(mapping["num"], mapping["den"]) {}
Fraction::Fraction(std::vector vector)
- : Fraction::Fraction(vector[0], vector[1]) {};
+ : Fraction::Fraction(vector[0], vector[1]) {}
// Full constructor
Fraction::Fraction(int num, int den) :
- num(num), den(den) {
-}
+ num(num), den(den) {}
// Return this fraction as a float (i.e. 1/2 = 0.5)
float Fraction::ToFloat() {
diff --git a/src/Fraction.h b/src/Fraction.h
index fb36e88b..3033cb92 100644
--- a/src/Fraction.h
+++ b/src/Fraction.h
@@ -38,53 +38,63 @@
namespace openshot {
- /**
- * @brief This class represents a fraction
- *
- * Fractions are often used in video editing to represent ratios and rates, for example:
- * pixel ratios, frames per second, timebase, and other common ratios. Fractions are preferred
- * over decimals due to their increased precision.
- */
- class Fraction {
- public:
- int num; /// pair);
+ /// Constructor that accepts a (num, den) pair
+ Fraction(std::pair pair);
- /// Constructor that takes a vector of length 2 (containing {num, den})
- Fraction(std::vector vector);
+ /// Constructor that takes a vector of length 2 (containing {num, den})
+ Fraction(std::vector vector);
- /// Constructor that takes a key-value mapping (keys: 'num'. 'den')
- Fraction(std::map mapping);
+ /// Constructor that takes a key-value mapping (keys: 'num'. 'den')
+ Fraction(std::map mapping);
- /// Calculate the greatest common denominator
- int GreatestCommonDenominator();
+ /// Calculate the greatest common denominator
+ int GreatestCommonDenominator();
- /// Reduce this fraction (i.e. 640/480 = 4/3)
- void Reduce();
+ /// Reduce this fraction (i.e. 640/480 = 4/3)
+ void Reduce();
- /// Return this fraction as a float (i.e. 1/2 = 0.5)
- float ToFloat();
+ /// Return this fraction as a float (i.e. 1/2 = 0.5)
+ float ToFloat();
- /// Return this fraction as a double (i.e. 1/2 = 0.5)
- double ToDouble() const;
+ /// Return this fraction as a double (i.e. 1/2 = 0.5)
+ double ToDouble() const;
- /// Return a rounded integer of the fraction (for example 30000/1001 returns 30)
- int ToInt();
-
- /// Return the reciprocal as a Fraction
- Fraction Reciprocal() const;
- };
+ /// Return a rounded integer of the fraction (for example 30000/1001 returns 30)
+ int ToInt();
+ /// Return the reciprocal as a Fraction
+ Fraction Reciprocal() const;
+};
+// Stream output operator for openshot::Fraction
+template
+std::basic_ostream&
+operator<<(std::basic_ostream& o, const openshot::Fraction& frac) {
+ std::basic_ostringstream s;
+ s.flags(o.flags());
+ s.imbue(o.getloc());
+ s.precision(o.precision());
+ s << "Fraction(" << frac.num << ", " << frac.den << ")";
+ return o << s.str();
}
+} // namespace openshot
#endif
diff --git a/src/Frame.cpp b/src/Frame.cpp
index 244b065f..aed38777 100644
--- a/src/Frame.cpp
+++ b/src/Frame.cpp
@@ -66,15 +66,15 @@ Frame::Frame(int64_t number, int width, int height, std::string color, int sampl
}
// Delegating Constructor - blank frame
-Frame::Frame() : Frame::Frame(1, 1, 1, "#000000", 0, 2) {};
+Frame::Frame() : Frame::Frame(1, 1, 1, "#000000", 0, 2) {}
// Delegating Constructor - image only
Frame::Frame(int64_t number, int width, int height, std::string color)
- : Frame::Frame(number, width, height, color, 0, 2) {};
+ : Frame::Frame(number, width, height, color, 0, 2) {}
// Delegating Constructor - audio only
Frame::Frame(int64_t number, int samples, int channels)
- : Frame::Frame(number, 1, 1, "#000000", samples, channels) {};
+ : Frame::Frame(number, 1, 1, "#000000", samples, channels) {}
// Copy constructor
@@ -918,7 +918,7 @@ cv::Mat Frame::Qimage2mat( std::shared_ptr& qimage) {
cv::mixChannels( &mat, 1, &mat2, 1, from_to, 3 );
cv::cvtColor(mat2, mat2, cv::COLOR_RGB2BGR);
return mat2;
-};
+}
// Get pointer to OpenCV image object
cv::Mat Frame::GetImageCV()
diff --git a/src/FrameMapper.cpp b/src/FrameMapper.cpp
index 9700b6ea..687ac595 100644
--- a/src/FrameMapper.cpp
+++ b/src/FrameMapper.cpp
@@ -28,6 +28,10 @@
* along with OpenShot Library. If not, see .
*/
+#include
+#include
+#include
+
#include "FrameMapper.h"
#include "Exceptions.h"
#include "Clip.h"
@@ -517,7 +521,7 @@ std::shared_ptr FrameMapper::GetFrame(int64_t requested_frame)
copy_samples.sample_end += EXTRA_INPUT_SAMPLES;
int samples_per_end_frame =
Frame::GetSamplesPerFrame(copy_samples.frame_end, original,
- reader->info.sample_rate, reader->info.channels);
+ reader->info.sample_rate, reader->info.channels);
if (copy_samples.sample_end >= samples_per_end_frame)
{
// check for wrapping
@@ -533,7 +537,7 @@ std::shared_ptr FrameMapper::GetFrame(int64_t requested_frame)
copy_samples.sample_start += EXTRA_INPUT_SAMPLES;
int samples_per_start_frame =
Frame::GetSamplesPerFrame(copy_samples.frame_start, original,
- reader->info.sample_rate, reader->info.channels);
+ reader->info.sample_rate, reader->info.channels);
if (copy_samples.sample_start >= samples_per_start_frame)
{
// check for wrapping
@@ -611,7 +615,7 @@ std::shared_ptr FrameMapper::GetFrame(int64_t requested_frame)
return final_cache.GetFrame(requested_frame);
}
-void FrameMapper::PrintMapping()
+void FrameMapper::PrintMapping(std::ostream* out)
{
// Check if mappings are dirty (and need to be recalculated)
if (is_dirty)
@@ -622,8 +626,16 @@ void FrameMapper::PrintMapping()
for (float map = 1; map <= frames.size(); map++)
{
MappedFrame frame = frames[map - 1];
- cout << "Target frame #: " << map << " mapped to original frame #:\t(" << frame.Odd.Frame << " odd, " << frame.Even.Frame << " even)" << endl;
- cout << " - Audio samples mapped to frame " << frame.Samples.frame_start << ":" << frame.Samples.sample_start << " to frame " << frame.Samples.frame_end << ":" << frame.Samples.sample_end << endl;
+ *out << "Target frame #: " << map
+ << " mapped to original frame #:\t("
+ << frame.Odd.Frame << " odd, "
+ << frame.Even.Frame << " even)" << std::endl;
+
+ *out << " - Audio samples mapped to frame "
+ << frame.Samples.frame_start << ":"
+ << frame.Samples.sample_start << " to frame "
+ << frame.Samples.frame_end << ":"
+ << frame.Samples.sample_end << endl;
}
}
@@ -733,7 +745,14 @@ void FrameMapper::SetJsonValue(const Json::Value root) {
// Change frame rate or audio mapping details
void FrameMapper::ChangeMapping(Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout)
{
- ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ChangeMapping", "target_fps.num", target_fps.num, "target_fps.den", target_fps.den, "target_pulldown", target_pulldown, "target_sample_rate", target_sample_rate, "target_channels", target_channels, "target_channel_layout", target_channel_layout);
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "FrameMapper::ChangeMapping",
+ "target_fps.num", target_fps.num,
+ "target_fps.den", target_fps.den,
+ "target_pulldown", target_pulldown,
+ "target_sample_rate", target_sample_rate,
+ "target_channels", target_channels,
+ "target_channel_layout", target_channel_layout);
// Mark as dirty
is_dirty = true;
@@ -779,7 +798,13 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig
int samples_in_frame = frame->GetAudioSamplesCount();
ChannelLayout channel_layout_in_frame = frame->ChannelsLayout();
- ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio", "frame->number", frame->number, "original_frame_number", original_frame_number, "channels_in_frame", channels_in_frame, "samples_in_frame", samples_in_frame, "sample_rate_in_frame", sample_rate_in_frame);
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "FrameMapper::ResampleMappedAudio",
+ "frame->number", frame->number,
+ "original_frame_number", original_frame_number,
+ "channels_in_frame", channels_in_frame,
+ "samples_in_frame", samples_in_frame,
+ "sample_rate_in_frame", sample_rate_in_frame);
// Get audio sample array
float* frame_samples_float = NULL;
@@ -815,7 +840,14 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig
delete[] frame_samples_float;
frame_samples_float = NULL;
- ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (got sample data from frame)", "frame->number", frame->number, "total_frame_samples", total_frame_samples, "target channels", info.channels, "channels_in_frame", channels_in_frame, "target sample_rate", info.sample_rate, "samples_in_frame", samples_in_frame);
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "FrameMapper::ResampleMappedAudio (got sample data from frame)",
+ "frame->number", frame->number,
+ "total_frame_samples", total_frame_samples,
+ "target channels", info.channels,
+ "channels_in_frame", channels_in_frame,
+ "target sample_rate", info.sample_rate,
+ "samples_in_frame", samples_in_frame);
// Create input frame (and allocate arrays)
@@ -823,8 +855,10 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig
AV_RESET_FRAME(audio_frame);
audio_frame->nb_samples = total_frame_samples / channels_in_frame;
- int error_code = avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) frame_samples,
- audio_frame->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * channels_in_frame, 1);
+ int buf_size = audio_frame->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * channels_in_frame;
+ int error_code = avcodec_fill_audio_frame(
+ audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16,
+ (uint8_t *) frame_samples, buf_size, 1);
if (error_code < 0)
{
@@ -837,7 +871,14 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig
// Update total samples & input frame size (due to bigger or smaller data types)
total_frame_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame->number), target, info.sample_rate, info.channels);
- ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (adjust # of samples)", "total_frame_samples", total_frame_samples, "info.sample_rate", info.sample_rate, "sample_rate_in_frame", sample_rate_in_frame, "info.channels", info.channels, "channels_in_frame", channels_in_frame, "original_frame_number", original_frame_number);
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "FrameMapper::ResampleMappedAudio (adjust # of samples)",
+ "total_frame_samples", total_frame_samples,
+ "info.sample_rate", info.sample_rate,
+ "sample_rate_in_frame", sample_rate_in_frame,
+ "info.channels", info.channels,
+ "channels_in_frame", channels_in_frame,
+ "original_frame_number", original_frame_number);
// Create output frame (and allocate arrays)
AVFrame *audio_converted = AV_ALLOCATE_FRAME();
@@ -845,32 +886,39 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig
audio_converted->nb_samples = total_frame_samples;
av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, total_frame_samples, AV_SAMPLE_FMT_S16, 0);
- ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (preparing for resample)", "in_sample_fmt", AV_SAMPLE_FMT_S16, "out_sample_fmt", AV_SAMPLE_FMT_S16, "in_sample_rate", sample_rate_in_frame, "out_sample_rate", info.sample_rate, "in_channels", channels_in_frame, "out_channels", info.channels);
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "FrameMapper::ResampleMappedAudio (preparing for resample)",
+ "in_sample_fmt", AV_SAMPLE_FMT_S16,
+ "out_sample_fmt", AV_SAMPLE_FMT_S16,
+ "in_sample_rate", sample_rate_in_frame,
+ "out_sample_rate", info.sample_rate,
+ "in_channels", channels_in_frame,
+ "out_channels", info.channels);
int nb_samples = 0;
// setup resample context
if (!avr) {
avr = SWR_ALLOC();
- av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
- av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
- av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
- av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
- av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
- av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
- av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
- av_opt_set_int(avr, "out_channels", info.channels, 0);
+ av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
+ av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
+ av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
+ av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
+ av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
+ av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
+ av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
+ av_opt_set_int(avr, "out_channels", info.channels, 0);
SWR_INIT(avr);
}
// Convert audio samples
- nb_samples = SWR_CONVERT(avr, // audio resample context
- audio_converted->data, // output data pointers
- audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
- audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
- audio_frame->data, // input data pointers
- audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
- audio_frame->nb_samples); // number of input samples to convert
+ nb_samples = SWR_CONVERT(avr, // audio resample context
+ audio_converted->data, // output data pointers
+ audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
+ audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
+ audio_frame->data, // input data pointers
+ audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
+ audio_frame->nb_samples); // number of input samples to convert
// Create a new array (to hold all resampled S16 audio samples)
int16_t* resampled_samples = new int16_t[(nb_samples * info.channels)];
@@ -889,7 +937,14 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig
int channel_buffer_size = nb_samples;
frame->ResizeAudio(info.channels, channel_buffer_size, info.sample_rate, info.channel_layout);
- ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (Audio successfully resampled)", "nb_samples", nb_samples, "total_frame_samples", total_frame_samples, "info.sample_rate", info.sample_rate, "channels_in_frame", channels_in_frame, "info.channels", info.channels, "info.channel_layout", info.channel_layout);
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "FrameMapper::ResampleMappedAudio (Audio successfully resampled)",
+ "nb_samples", nb_samples,
+ "total_frame_samples", total_frame_samples,
+ "info.sample_rate", info.sample_rate,
+ "channels_in_frame", channels_in_frame,
+ "info.channels", info.channels,
+ "info.channel_layout", info.channel_layout);
// Array of floats (to hold samples for each channel)
float *channel_buffer = new float[channel_buffer_size];
@@ -929,7 +984,10 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig
// Add samples to frame for this channel
frame->AddAudio(true, channel_filter, 0, channel_buffer, position, 1.0f);
- ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (Add audio to channel)", "number of samples", position, "channel_filter", channel_filter);
+ ZmqLogger::Instance()->AppendDebugMethod(
+ "FrameMapper::ResampleMappedAudio (Add audio to channel)",
+ "number of samples", position,
+ "channel_filter", channel_filter);
}
// Update frame's audio meta data
@@ -957,9 +1015,10 @@ int64_t FrameMapper::AdjustFrameNumber(int64_t clip_frame_number) {
start = parent->Start();
}
- // Adjust start frame and position based on parent clip. This prevents ensures the same
- // frame # is used by mapped readers and clips, when calculating samples per frame. Thus,
- // this prevents gaps and mismatches in # of samples.
+ // Adjust start frame and position based on parent clip.
+ // This ensures the same frame # is used by mapped readers and clips,
+ // when calculating samples per frame.
+ // Thus, this prevents gaps and mismatches in # of samples.
int64_t clip_start_frame = (start * info.fps.ToDouble()) + 1;
int64_t clip_start_position = round(position * info.fps.ToDouble()) + 1;
int64_t frame_number = clip_frame_number + clip_start_position - clip_start_frame;
diff --git a/src/FrameMapper.h b/src/FrameMapper.h
index 62615cfb..813c644f 100644
--- a/src/FrameMapper.h
+++ b/src/FrameMapper.h
@@ -33,9 +33,9 @@
#include
#include
-#include
#include
#include
+
#include "CacheMemory.h"
#include "ReaderBase.h"
#include "Frame.h"
@@ -211,7 +211,7 @@ namespace openshot
void Open() override;
/// Print all of the original frames and which new frames they map to
- void PrintMapping();
+ void PrintMapping(std::ostream* out=&std::cout);
/// Get the current reader
ReaderBase* Reader();
diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp
index 4107f2de..e25f4d7c 100644
--- a/src/KeyFrame.cpp
+++ b/src/KeyFrame.cpp
@@ -31,12 +31,14 @@
#include "KeyFrame.h"
#include "Exceptions.h"
-#include
-#include
-#include
-#include // For assert()
-#include // For std::cout
-#include // For std::setprecision
+#include // For std::lower_bound, std::move_backward
+#include // For std::less, std::less_equal, etc…
+#include // For std::swap
+#include // For std::accumulate
+#include // For assert()
+#include // For fabs, round
+#include // For std::cout
+#include // For std::setprecision
using namespace std;
using namespace openshot;
@@ -559,22 +561,51 @@ void Keyframe::UpdatePoint(int64_t index, Point p) {
AddPoint(p);
}
-void Keyframe::PrintPoints() const {
- cout << fixed << setprecision(4);
- for (std::vector::const_iterator it = Points.begin(); it != Points.end(); it++) {
- Point p = *it;
- cout << p.co.X << "\t" << p.co.Y << endl;
- }
+void Keyframe::PrintPoints(std::ostream* out) const {
+ *out << std::right << std::setprecision(4) << std::setfill(' ');
+ for (const auto& p : Points) {
+ *out << std::defaultfloat
+ << std::setw(6) << p.co.X
+ << std::setw(14) << std::fixed << p.co.Y
+ << '\n';
+ }
+ *out << std::flush;
}
-void Keyframe::PrintValues() const {
- cout << fixed << setprecision(4);
- cout << "Frame Number (X)\tValue (Y)\tIs Increasing\tRepeat Numerator\tRepeat Denominator\tDelta (Y Difference)\n";
+void Keyframe::PrintValues(std::ostream* out) const {
+ // Column widths
+ std::vector w{10, 12, 8, 11, 19};
- for (int64_t i = 1; i < GetLength(); ++i) {
- cout << i << "\t" << GetValue(i) << "\t" << IsIncreasing(i) << "\t" ;
- cout << GetRepeatFraction(i).num << "\t" << GetRepeatFraction(i).den << "\t" << GetDelta(i) << "\n";
- }
+ *out << std::right << std::setfill(' ') << std::boolalpha
+ << std::setprecision(4);
+ // Headings
+ *out << "│"
+ << std::setw(w[0]) << "Frame# (X)" << " │"
+ << std::setw(w[1]) << "Y Value" << " │"
+ << std::setw(w[2]) << "Delta Y" << " │ "
+ << std::setw(w[3]) << "Increasing?" << " │ "
+ << std::setw(w[4]) << std::left << "Repeat Fraction" << std::right
+ << "│\n";
+ // Divider
+ *out << "├───────────"
+ << "┼─────────────"
+ << "┼─────────"
+ << "┼─────────────"
+ << "┼────────────────────┤\n";
+
+ for (int64_t i = 1; i < GetLength(); ++i) {
+ *out << "│"
+ << std::setw(w[0]-2) << std::defaultfloat << i
+ << (Contains(Point(i, 1)) ? " *" : " ") << " │"
+ << std::setw(w[1]) << std::fixed << GetValue(i) << " │"
+ << std::setw(w[2]) << std::defaultfloat << std::showpos
+ << GetDelta(i) << " │ " << std::noshowpos
+ << std::setw(w[3]) << IsIncreasing(i) << " │ "
+ << std::setw(w[4]) << std::left << GetRepeatFraction(i)
+ << std::right << "│\n";
+ }
+ *out << " * = Keyframe point (non-interpolated)\n";
+ *out << std::flush;
}
diff --git a/src/KeyFrame.h b/src/KeyFrame.h
index 6da34cac..45624dd2 100644
--- a/src/KeyFrame.h
+++ b/src/KeyFrame.h
@@ -31,7 +31,7 @@
#ifndef OPENSHOT_KEYFRAME_H
#define OPENSHOT_KEYFRAME_H
-#include
+#include
#include
#include "Fraction.h"
@@ -160,10 +160,10 @@ namespace openshot {
void UpdatePoint(int64_t index, Point p);
/// Print a list of points
- void PrintPoints() const;
+ void PrintPoints(std::ostream* out=&std::cout) const;
/// Print just the Y value of the point's primary coordinate
- void PrintValues() const;
+ void PrintValues(std::ostream* out=&std::cout) const;
};
diff --git a/src/Point.cpp b/src/Point.cpp
index 44b6883f..b11aa7ce 100644
--- a/src/Point.cpp
+++ b/src/Point.cpp
@@ -35,24 +35,24 @@ using namespace std;
using namespace openshot;
// Default constructor
-Point::Point() : Point::Point(Coordinate(1, 0), BEZIER, AUTO) {};
+Point::Point() : Point::Point(Coordinate(1, 0), BEZIER, AUTO) {}
// Constructor which creates a single coordinate at X=1
-Point::Point(float y) : Point::Point(Coordinate(1, y), CONSTANT, AUTO) {};
+Point::Point(float y) : Point::Point(Coordinate(1, y), CONSTANT, AUTO) {}
// Constructor which creates a Bezier curve with point at (x, y)
-Point::Point(float x, float y) : Point::Point(Coordinate(x, y), BEZIER, AUTO) {};
+Point::Point(float x, float y) : Point::Point(Coordinate(x, y), BEZIER, AUTO) {}
// Constructor which also creates a Point, setting X,Y, and interpolation.
Point::Point(float x, float y, InterpolationType interpolation)
- : Point::Point(Coordinate(x, y), interpolation, AUTO) {};
+ : Point::Point(Coordinate(x, y), interpolation, AUTO) {}
// Direct Coordinate-accepting constructors
-Point::Point(const Coordinate& co) : Point::Point(co, BEZIER, AUTO) {};
+Point::Point(const Coordinate& co) : Point::Point(co, BEZIER, AUTO) {}
Point::Point(const Coordinate& co, InterpolationType interpolation)
- : Point::Point(co, interpolation, AUTO) {};
+ : Point::Point(co, interpolation, AUTO) {}
Point::Point(const Coordinate& co, InterpolationType interpolation, HandleType handle_type) :
co(co), interpolation(interpolation), handle_type(handle_type) {
diff --git a/src/Point.h b/src/Point.h
index 1795c469..118e6d39 100644
--- a/src/Point.h
+++ b/src/Point.h
@@ -37,95 +37,118 @@
namespace openshot
{
- /**
- * @brief This controls how a Keyframe uses this point to interpolate between two points.
- *
- * Bezier is a smooth curve. Linear is a straight line. Constant is a jump from the
- * previous point to this one.
- */
- enum InterpolationType {
- BEZIER, ///< Bezier curves are quadratic curves, which create a smooth curve.
- LINEAR, ///< Linear curves are angular, straight lines between two points.
- CONSTANT ///< Constant curves jump from their previous position to a new one (with no interpolation).
- };
+/**
+ * @brief This controls how a Keyframe uses this point to interpolate between two points.
+ *
+ * Bezier is a smooth curve. Linear is a straight line. Constant is a jump from the
+ * previous point to this one.
+ */
+enum InterpolationType {
+ BEZIER, ///< Bezier curves are quadratic curves, which create a smooth curve.
+ LINEAR, ///< Linear curves are angular, straight lines between two points.
+ CONSTANT ///< Constant curves jump from their previous position to a new one (with no interpolation).
+};
- /**
- * @brief When BEZIER interpolation is used, the point's left and right handles are used
- * to influence the direction of the curve.
- *
- * AUTO will try and adjust the handles automatically, to achieve the smoothest curves.
- * MANUAL will leave the handles alone, making it the responsibility of the user to set them.
- */
- enum HandleType {
- AUTO, ///< Automatically adjust the handles to achieve the smoothest curve
- MANUAL ///< Do not automatically adjust handles (set them manually)
- };
+/**
+ * @brief When BEZIER interpolation is used, the point's left and right handles are used
+ * to influence the direction of the curve.
+ *
+ * AUTO will try and adjust the handles automatically, to achieve the smoothest curves.
+ * MANUAL will leave the handles alone, making it the responsibility of the user to set them.
+ */
+enum HandleType {
+ AUTO, ///< Automatically adjust the handles to achieve the smoothest curve
+ MANUAL ///< Do not automatically adjust handles (set them manually)
+};
- /**
- * @brief A Point is the basic building block of a key-frame curve.
- *
- * Points have a primary coordinate and a left and right handle coordinate.
- * The handles are used to influence the direction of the curve as it
- * moves between the primary coordinate and the next primary coordinate when the
- * interpolation mode is BEZIER. When using LINEAR or CONSTANT, the handles are
- * ignored.
- *
- * Please see the following Example Code:
- * \code
- * Coordinate c1(3,9);
- * Point p1(c1, BEZIER);
- * assert(c1.X == 3);
- * assert(c1.Y == 9);
- *
- * \endcode
- */
- class Point {
- public:
- Coordinate co; ///< This is the primary coordinate
- Coordinate handle_left; ///< This is the left handle coordinate (in percentages from 0 to 1)
- Coordinate handle_right; ///< This is the right handle coordinate (in percentages from 0 to 1)
- InterpolationType interpolation; ///< This is the interpolation mode
- HandleType handle_type; ///< This is the handle mode
+/**
+ * @brief A Point is the basic building block of a key-frame curve.
+ *
+ * Points have a primary coordinate and a left and right handle coordinate.
+ * The handles are used to influence the direction of the curve as it
+ * moves between the primary coordinate and the next primary coordinate when the
+ * interpolation mode is BEZIER. When using LINEAR or CONSTANT, the handles are
+ * ignored.
+ *
+ * Please see the following Example Code:
+ * \code
+ * Coordinate c1(3,9);
+ * Point p1(c1, BEZIER);
+ * assert(c1.X == 3);
+ * assert(c1.Y == 9);
+ *
+ * \endcode
+ */
+class Point {
+public:
+ Coordinate co; ///< This is the primary coordinate
+ Coordinate handle_left; ///< This is the left handle coordinate (in percentages from 0 to 1)
+ Coordinate handle_right; ///< This is the right handle coordinate (in percentages from 0 to 1)
+ InterpolationType interpolation; ///< This is the interpolation mode
+ HandleType handle_type; ///< This is the handle mode
- /// Default constructor (defaults to 1,0)
- Point();
+ /// Default constructor (defaults to 1,0)
+ Point();
- /// Constructor which creates a single coordinate at X=1
- Point(float y);
+ /// Constructor which creates a single coordinate at X=1
+ Point(float y);
- /// Constructor which also creates a Point and sets the X and Y of the Point.
- Point(float x, float y);
+ /// Constructor which also creates a Point and sets the X and Y of the Point.
+ Point(float x, float y);
- /// Constructor which also creates a Point and sets the X,Y, and interpolation of the Point.
- Point(float x, float y, InterpolationType interpolation);
+ /// Constructor which also creates a Point and sets the X,Y, and interpolation of the Point.
+ Point(float x, float y, InterpolationType interpolation);
- /// Constructor which takes a coordinate
- Point(const Coordinate& co);
+ /// Constructor which takes a coordinate
+ Point(const Coordinate& co);
- /// Constructor which takes a coordinate and interpolation mode
- Point(const Coordinate& co, InterpolationType interpolation);
+ /// Constructor which takes a coordinate and interpolation mode
+ Point(const Coordinate& co, InterpolationType interpolation);
- /// Constructor which takes a coordinate, interpolation mode, and handle type
- Point(const Coordinate& co, InterpolationType interpolation, HandleType handle_type);
+ /// Constructor which takes a coordinate, interpolation mode, and handle type
+ Point(const Coordinate& co, InterpolationType interpolation, HandleType handle_type);
- /// Set the left and right handles to a percent of the primary coordinate (0 to 1)
- /// Defaults to a smooth curve (Ease in and out)
- void Initialize_Handles();
+ /// Set the left and right handles to a percent of the primary coordinate (0 to 1)
+ /// Defaults to a smooth curve (Ease in and out)
+ void Initialize_Handles();
- /// Set the left handle to a percent of the primary coordinate (0 to 1)
- void Initialize_LeftHandle(float x, float y);
+ /// Set the left handle to a percent of the primary coordinate (0 to 1)
+ void Initialize_LeftHandle(float x, float y);
- /// Set the right handle to a percent of the primary coordinate (0 to 1)
- void Initialize_RightHandle(float x, float y);
+ /// Set the right handle to a percent of the primary coordinate (0 to 1)
+ void Initialize_RightHandle(float x, float y);
- // Get and Set JSON methods
- std::string Json() const; ///< Generate JSON string of this object
- Json::Value JsonValue() const; ///< Generate Json::Value for this object
- void SetJson(const std::string value); ///< Load JSON string into this object
- void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object
+ // Get and Set JSON methods
+ std::string Json() const; ///< Generate JSON string of this object
+ Json::Value JsonValue() const; ///< Generate Json::Value for this object
+ void SetJson(const std::string value); ///< Load JSON string into this object
+ void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object
- };
+};
+// Stream output operator for openshot::Point
+template
+std::basic_ostream&
+operator<<(std::basic_ostream& o, const openshot::Point& p) {
+ std::basic_ostringstream s;
+ s.flags(o.flags());
+ s.imbue(o.getloc());
+ s.precision(o.precision());
+ s << "co" << p.co;
+ switch(p.interpolation) {
+ case(InterpolationType::LINEAR):
+ s << " LINEAR";
+ break;
+ case(InterpolationType::CONSTANT):
+ s << " CONSTANT";
+ break;
+ case(InterpolationType::BEZIER):
+ s << " BEZIER[L" << p.handle_left << ",R" << p.handle_right << ']';
+ break;
+ }
+ return o << s.str();
}
+} // namespace openshot
+
#endif
diff --git a/src/ReaderBase.cpp b/src/ReaderBase.cpp
index 127fefbe..63b5cada 100644
--- a/src/ReaderBase.cpp
+++ b/src/ReaderBase.cpp
@@ -28,8 +28,14 @@
* along with OpenShot Library. If not, see .
*/
+#include
+#include
+#include
+
#include "ReaderBase.h"
+#include "Json.h"
+
using namespace openshot;
/// Constructor for the base reader, where many things are initialized.
@@ -67,49 +73,49 @@ ReaderBase::ReaderBase()
}
// Display file information
-void ReaderBase::DisplayInfo() {
- std::cout << std::fixed << std::setprecision(2) << std::boolalpha;
- std::cout << "----------------------------" << std::endl;
- std::cout << "----- File Information -----" << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "--> Has Video: " << info.has_video << std::endl;
- std::cout << "--> Has Audio: " << info.has_audio << std::endl;
- std::cout << "--> Has Single Image: " << info.has_single_image << std::endl;
- std::cout << "--> Duration: " << info.duration << " Seconds" << std::endl;
- std::cout << "--> File Size: " << double(info.file_size) / 1024 / 1024 << " MB" << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "----- Video Attributes -----" << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "--> Width: " << info.width << std::endl;
- std::cout << "--> Height: " << info.height << std::endl;
- std::cout << "--> Pixel Format: " << info.pixel_format << std::endl;
- std::cout << "--> Frames Per Second: " << info.fps.ToDouble() << " (" << info.fps.num << "/" << info.fps.den << ")" << std::endl;
- std::cout << "--> Video Bit Rate: " << info.video_bit_rate/1000 << " kb/s" << std::endl;
- std::cout << "--> Pixel Ratio: " << info.pixel_ratio.ToDouble() << " (" << info.pixel_ratio.num << "/" << info.pixel_ratio.den << ")" << std::endl;
- std::cout << "--> Display Aspect Ratio: " << info.display_ratio.ToDouble() << " (" << info.display_ratio.num << "/" << info.display_ratio.den << ")" << std::endl;
- std::cout << "--> Video Codec: " << info.vcodec << std::endl;
- std::cout << "--> Video Length: " << info.video_length << " Frames" << std::endl;
- std::cout << "--> Video Stream Index: " << info.video_stream_index << std::endl;
- std::cout << "--> Video Timebase: " << info.video_timebase.ToDouble() << " (" << info.video_timebase.num << "/" << info.video_timebase.den << ")" << std::endl;
- std::cout << "--> Interlaced: " << info.interlaced_frame << std::endl;
- std::cout << "--> Interlaced: Top Field First: " << info.top_field_first << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "----- Audio Attributes -----" << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "--> Audio Codec: " << info.acodec << std::endl;
- std::cout << "--> Audio Bit Rate: " << info.audio_bit_rate/1000 << " kb/s" << std::endl;
- std::cout << "--> Sample Rate: " << info.sample_rate << " Hz" << std::endl;
- std::cout << "--> # of Channels: " << info.channels << std::endl;
- std::cout << "--> Channel Layout: " << info.channel_layout << std::endl;
- std::cout << "--> Audio Stream Index: " << info.audio_stream_index << std::endl;
- std::cout << "--> Audio Timebase: " << info.audio_timebase.ToDouble() << " (" << info.audio_timebase.num << "/" << info.audio_timebase.den << ")" << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "--------- Metadata ---------" << std::endl;
- std::cout << "----------------------------" << std::endl;
+void ReaderBase::DisplayInfo(std::ostream* out) {
+ *out << std::fixed << std::setprecision(2) << std::boolalpha;
+ *out << "----------------------------" << std::endl;
+ *out << "----- File Information -----" << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "--> Has Video: " << info.has_video << std::endl;
+ *out << "--> Has Audio: " << info.has_audio << std::endl;
+ *out << "--> Has Single Image: " << info.has_single_image << std::endl;
+ *out << "--> Duration: " << info.duration << " Seconds" << std::endl;
+ *out << "--> File Size: " << double(info.file_size) / 1024 / 1024 << " MB" << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "----- Video Attributes -----" << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "--> Width: " << info.width << std::endl;
+ *out << "--> Height: " << info.height << std::endl;
+ *out << "--> Pixel Format: " << info.pixel_format << std::endl;
+ *out << "--> Frames Per Second: " << info.fps.ToDouble() << " (" << info.fps.num << "/" << info.fps.den << ")" << std::endl;
+ *out << "--> Video Bit Rate: " << info.video_bit_rate/1000 << " kb/s" << std::endl;
+ *out << "--> Pixel Ratio: " << info.pixel_ratio.ToDouble() << " (" << info.pixel_ratio.num << "/" << info.pixel_ratio.den << ")" << std::endl;
+ *out << "--> Display Aspect Ratio: " << info.display_ratio.ToDouble() << " (" << info.display_ratio.num << "/" << info.display_ratio.den << ")" << std::endl;
+ *out << "--> Video Codec: " << info.vcodec << std::endl;
+ *out << "--> Video Length: " << info.video_length << " Frames" << std::endl;
+ *out << "--> Video Stream Index: " << info.video_stream_index << std::endl;
+ *out << "--> Video Timebase: " << info.video_timebase.ToDouble() << " (" << info.video_timebase.num << "/" << info.video_timebase.den << ")" << std::endl;
+ *out << "--> Interlaced: " << info.interlaced_frame << std::endl;
+ *out << "--> Interlaced: Top Field First: " << info.top_field_first << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "----- Audio Attributes -----" << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "--> Audio Codec: " << info.acodec << std::endl;
+ *out << "--> Audio Bit Rate: " << info.audio_bit_rate/1000 << " kb/s" << std::endl;
+ *out << "--> Sample Rate: " << info.sample_rate << " Hz" << std::endl;
+ *out << "--> # of Channels: " << info.channels << std::endl;
+ *out << "--> Channel Layout: " << info.channel_layout << std::endl;
+ *out << "--> Audio Stream Index: " << info.audio_stream_index << std::endl;
+ *out << "--> Audio Timebase: " << info.audio_timebase.ToDouble() << " (" << info.audio_timebase.num << "/" << info.audio_timebase.den << ")" << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "--------- Metadata ---------" << std::endl;
+ *out << "----------------------------" << std::endl;
// Iterate through metadata
for (auto it : info.metadata)
- std::cout << "--> " << it.first << ": " << it.second << std::endl;
+ *out << "--> " << it.first << ": " << it.second << std::endl;
}
// Generate Json::Value for this object
diff --git a/src/ReaderBase.h b/src/ReaderBase.h
index 7b7847a8..4d2d3afa 100644
--- a/src/ReaderBase.h
+++ b/src/ReaderBase.h
@@ -31,11 +31,9 @@
#ifndef OPENSHOT_READER_BASE_H
#define OPENSHOT_READER_BASE_H
-#include
-#include
#include
-#include
-#include
+#include
+
#include "CacheMemory.h"
#include "ChannelLayouts.h"
#include "ClipBase.h"
@@ -120,7 +118,7 @@ namespace openshot
virtual void Close() = 0;
/// Display file information in the standard output stream (stdout)
- void DisplayInfo();
+ void DisplayInfo(std::ostream* out=&std::cout);
/// Get the cache object used by this reader (note: not all readers use cache)
virtual openshot::CacheBase* GetCache() = 0;
diff --git a/src/WriterBase.cpp b/src/WriterBase.cpp
index fff93988..8faab981 100644
--- a/src/WriterBase.cpp
+++ b/src/WriterBase.cpp
@@ -28,6 +28,9 @@
* along with OpenShot Library. If not, see .
*/
+#include
+#include
+
#include "WriterBase.h"
#include "Exceptions.h"
@@ -100,43 +103,43 @@ void WriterBase::CopyReaderInfo(ReaderBase* reader)
}
// Display file information
-void WriterBase::DisplayInfo() {
- std::cout << std::fixed << std::setprecision(2) << std::boolalpha;
- std::cout << "----------------------------" << std::endl;
- std::cout << "----- File Information -----" << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "--> Has Video: " << info.has_video << std::endl;
- std::cout << "--> Has Audio: " << info.has_audio << std::endl;
- std::cout << "--> Has Single Image: " << info.has_single_image << std::endl;
- std::cout << "--> Duration: " << info.duration << " Seconds" << std::endl;
- std::cout << "--> File Size: " << double(info.file_size) / 1024 / 1024 << " MB" << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "----- Video Attributes -----" << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "--> Width: " << info.width << std::endl;
- std::cout << "--> Height: " << info.height << std::endl;
- std::cout << "--> Pixel Format: " << info.pixel_format << std::endl;
- std::cout << "--> Frames Per Second: " << info.fps.ToDouble() << " (" << info.fps.num << "/" << info.fps.den << ")" << std::endl;
- std::cout << "--> Video Bit Rate: " << info.video_bit_rate/1000 << " kb/s" << std::endl;
- std::cout << "--> Pixel Ratio: " << info.pixel_ratio.ToDouble() << " (" << info.pixel_ratio.num << "/" << info.pixel_ratio.den << ")" << std::endl;
- std::cout << "--> Display Aspect Ratio: " << info.display_ratio.ToDouble() << " (" << info.display_ratio.num << "/" << info.display_ratio.den << ")" << std::endl;
- std::cout << "--> Video Codec: " << info.vcodec << std::endl;
- std::cout << "--> Video Length: " << info.video_length << " Frames" << std::endl;
- std::cout << "--> Video Stream Index: " << info.video_stream_index << std::endl;
- std::cout << "--> Video Timebase: " << info.video_timebase.ToDouble() << " (" << info.video_timebase.num << "/" << info.video_timebase.den << ")" << std::endl;
- std::cout << "--> Interlaced: " << info.interlaced_frame << std::endl;
- std::cout << "--> Interlaced: Top Field First: " << info.top_field_first << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "----- Audio Attributes -----" << std::endl;
- std::cout << "----------------------------" << std::endl;
- std::cout << "--> Audio Codec: " << info.acodec << std::endl;
- std::cout << "--> Audio Bit Rate: " << info.audio_bit_rate/1000 << " kb/s" << std::endl;
- std::cout << "--> Sample Rate: " << info.sample_rate << " Hz" << std::endl;
- std::cout << "--> # of Channels: " << info.channels << std::endl;
- std::cout << "--> Channel Layout: " << info.channel_layout << std::endl;
- std::cout << "--> Audio Stream Index: " << info.audio_stream_index << std::endl;
- std::cout << "--> Audio Timebase: " << info.audio_timebase.ToDouble() << " (" << info.audio_timebase.num << "/" << info.audio_timebase.den << ")" << std::endl;
- std::cout << "----------------------------" << std::endl;
+void WriterBase::DisplayInfo(std::ostream* out) {
+ *out << std::fixed << std::setprecision(2) << std::boolalpha;
+ *out << "----------------------------" << std::endl;
+ *out << "----- File Information -----" << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "--> Has Video: " << info.has_video << std::endl;
+ *out << "--> Has Audio: " << info.has_audio << std::endl;
+ *out << "--> Has Single Image: " << info.has_single_image << std::endl;
+ *out << "--> Duration: " << info.duration << " Seconds" << std::endl;
+ *out << "--> File Size: " << double(info.file_size) / 1024 / 1024 << " MB" << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "----- Video Attributes -----" << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "--> Width: " << info.width << std::endl;
+ *out << "--> Height: " << info.height << std::endl;
+ *out << "--> Pixel Format: " << info.pixel_format << std::endl;
+ *out << "--> Frames Per Second: " << info.fps.ToDouble() << " (" << info.fps.num << "/" << info.fps.den << ")" << std::endl;
+ *out << "--> Video Bit Rate: " << info.video_bit_rate/1000 << " kb/s" << std::endl;
+ *out << "--> Pixel Ratio: " << info.pixel_ratio.ToDouble() << " (" << info.pixel_ratio.num << "/" << info.pixel_ratio.den << ")" << std::endl;
+ *out << "--> Display Aspect Ratio: " << info.display_ratio.ToDouble() << " (" << info.display_ratio.num << "/" << info.display_ratio.den << ")" << std::endl;
+ *out << "--> Video Codec: " << info.vcodec << std::endl;
+ *out << "--> Video Length: " << info.video_length << " Frames" << std::endl;
+ *out << "--> Video Stream Index: " << info.video_stream_index << std::endl;
+ *out << "--> Video Timebase: " << info.video_timebase.ToDouble() << " (" << info.video_timebase.num << "/" << info.video_timebase.den << ")" << std::endl;
+ *out << "--> Interlaced: " << info.interlaced_frame << std::endl;
+ *out << "--> Interlaced: Top Field First: " << info.top_field_first << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "----- Audio Attributes -----" << std::endl;
+ *out << "----------------------------" << std::endl;
+ *out << "--> Audio Codec: " << info.acodec << std::endl;
+ *out << "--> Audio Bit Rate: " << info.audio_bit_rate/1000 << " kb/s" << std::endl;
+ *out << "--> Sample Rate: " << info.sample_rate << " Hz" << std::endl;
+ *out << "--> # of Channels: " << info.channels << std::endl;
+ *out << "--> Channel Layout: " << info.channel_layout << std::endl;
+ *out << "--> Audio Stream Index: " << info.audio_stream_index << std::endl;
+ *out << "--> Audio Timebase: " << info.audio_timebase.ToDouble() << " (" << info.audio_timebase.num << "/" << info.audio_timebase.den << ")" << std::endl;
+ *out << "----------------------------" << std::endl;
}
// Generate JSON string of this object
diff --git a/src/WriterBase.h b/src/WriterBase.h
index d18f329d..3939ca6e 100644
--- a/src/WriterBase.h
+++ b/src/WriterBase.h
@@ -32,7 +32,7 @@
#define OPENSHOT_WRITER_BASE_H
#include
-#include
+
#include "ChannelLayouts.h"
#include "Fraction.h"
#include "Frame.h"
@@ -113,7 +113,7 @@ namespace openshot
void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object
/// Display file information in the standard output stream (stdout)
- void DisplayInfo();
+ void DisplayInfo(std::ostream* out=&std::cout);
/// Open the writer (and start initializing streams)
virtual void Open() = 0;
diff --git a/tests/FFmpegReader.cpp b/tests/FFmpegReader.cpp
index 217d601c..747ae0e2 100644
--- a/tests/FFmpegReader.cpp
+++ b/tests/FFmpegReader.cpp
@@ -39,7 +39,6 @@
#include "Timeline.h"
#include "Json.h"
-using namespace std;
using namespace openshot;
TEST_CASE( "Invalid_Path", "[libopenshot][ffmpegreader]" )
@@ -51,7 +50,7 @@ TEST_CASE( "Invalid_Path", "[libopenshot][ffmpegreader]" )
TEST_CASE( "GetFrame_Before_Opening", "[libopenshot][ffmpegreader]" )
{
// Create a reader
- stringstream path;
+ std::stringstream path;
path << TEST_MEDIA_PATH << "piano.wav";
FFmpegReader r(path.str());
@@ -62,7 +61,7 @@ TEST_CASE( "GetFrame_Before_Opening", "[libopenshot][ffmpegreader]" )
TEST_CASE( "Check_Audio_File", "[libopenshot][ffmpegreader]" )
{
// Create a reader
- stringstream path;
+ std::stringstream path;
path << TEST_MEDIA_PATH << "piano.wav";
FFmpegReader r(path.str());
r.Open();
@@ -92,7 +91,7 @@ TEST_CASE( "Check_Audio_File", "[libopenshot][ffmpegreader]" )
TEST_CASE( "Check_Video_File", "[libopenshot][ffmpegreader]" )
{
// Create a reader
- stringstream path;
+ std::stringstream path;
path << TEST_MEDIA_PATH << "test.mp4";
FFmpegReader r(path.str());
r.Open();
@@ -138,7 +137,7 @@ TEST_CASE( "Check_Video_File", "[libopenshot][ffmpegreader]" )
TEST_CASE( "Seek", "[libopenshot][ffmpegreader]" )
{
// Create a reader
- stringstream path;
+ std::stringstream path;
path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4";
FFmpegReader r(path.str());
r.Open();
@@ -195,7 +194,7 @@ TEST_CASE( "Seek", "[libopenshot][ffmpegreader]" )
TEST_CASE( "Frame_Rate", "[libopenshot][ffmpegreader]" )
{
// Create a reader
- stringstream path;
+ std::stringstream path;
path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4";
FFmpegReader r(path.str());
r.Open();
@@ -211,7 +210,7 @@ TEST_CASE( "Frame_Rate", "[libopenshot][ffmpegreader]" )
TEST_CASE( "Multiple_Open_and_Close", "[libopenshot][ffmpegreader]" )
{
// Create a reader
- stringstream path;
+ std::stringstream path;
path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4";
FFmpegReader r(path.str());
r.Open();
@@ -247,7 +246,7 @@ TEST_CASE( "Multiple_Open_and_Close", "[libopenshot][ffmpegreader]" )
TEST_CASE( "verify parent Timeline", "[libopenshot][ffmpegreader]" )
{
// Create a reader
- stringstream path;
+ std::stringstream path;
path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4";
FFmpegReader r(path.str());
r.Open();
@@ -273,3 +272,34 @@ TEST_CASE( "verify parent Timeline", "[libopenshot][ffmpegreader]" )
CHECK(r.GetFrame(1)->GetImage()->width() == 640);
CHECK(r.GetFrame(1)->GetImage()->height() == 360);
}
+
+TEST_CASE( "DisplayInfo", "[libopenshot][ffmpegreader]" )
+{
+ // Create a reader
+ std::stringstream path;
+ path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4";
+ FFmpegReader r(path.str());
+ r.Open();
+
+ std::string expected(R"(----------------------------
+----- File Information -----
+----------------------------
+--> Has Video: true
+--> Has Audio: true
+--> Has Single Image: false
+--> Duration: 51.95 Seconds
+--> File Size: 7.26 MB
+----------------------------
+----- Video Attributes -----
+----------------------------
+--> Width: 1280
+--> Height: 720)");
+
+ // Store the DisplayInfo() text in 'output'
+ std::stringstream output;
+ r.DisplayInfo(&output);
+
+ // Compare a [0, expected.size()) substring of output to expected
+ auto compare_value = output.str().compare(0, expected.size(), expected);
+ CHECK(compare_value == 0);
+}
diff --git a/tests/FFmpegWriter.cpp b/tests/FFmpegWriter.cpp
index 059bbb4d..adb555b2 100644
--- a/tests/FFmpegWriter.cpp
+++ b/tests/FFmpegWriter.cpp
@@ -45,7 +45,7 @@ using namespace openshot;
TEST_CASE( "Webm", "[libopenshot][ffmpegwriter]" )
{
// Reader
- stringstream path;
+ std::stringstream path;
path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4";
FFmpegReader r(path.str());
r.Open();
@@ -92,7 +92,7 @@ TEST_CASE( "Webm", "[libopenshot][ffmpegwriter]" )
TEST_CASE( "Options_Overloads", "[libopenshot][ffmpegwriter]" )
{
// Reader
- stringstream path;
+ std::stringstream path;
path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4";
FFmpegReader r(path.str());
r.Open();
@@ -129,3 +129,76 @@ TEST_CASE( "Options_Overloads", "[libopenshot][ffmpegwriter]" )
CHECK_FALSE(r1.info.interlaced_frame);
CHECK(r1.info.top_field_first == true);
}
+
+
+TEST_CASE( "DisplayInfo", "[libopenshot][ffmpegwriter]" )
+{
+ // Reader
+ std::stringstream path;
+ path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4";
+ FFmpegReader r(path.str());
+ r.Open();
+
+ /* WRITER ---------------- */
+ FFmpegWriter w("output1.webm");
+
+ // Set options
+ w.SetAudioOptions(true, "libvorbis", 44100, 2, LAYOUT_STEREO, 188000);
+ w.SetVideoOptions(
+ true, "libvpx",
+ Fraction(24,1),
+ 1280, 720,
+ Fraction(1,1),
+ false, false,
+ 30000000);
+
+ // Open writer
+ w.Open();
+
+ std::string expected(
+ R"(----------------------------
+----- File Information -----
+----------------------------
+--> Has Video: true
+--> Has Audio: true
+--> Has Single Image: false
+--> Duration: 0.00 Seconds
+--> File Size: 0.00 MB
+----------------------------
+----- Video Attributes -----
+----------------------------
+--> Width: 1280
+--> Height: 720
+--> Pixel Format: -1
+--> Frames Per Second: 24.00 (24/1)
+--> Video Bit Rate: 30000 kb/s
+--> Pixel Ratio: 1.00 (1/1)
+--> Display Aspect Ratio: 1.78 (16/9)
+--> Video Codec: libvpx
+--> Video Length: 0 Frames
+--> Video Stream Index: -1
+--> Video Timebase: 0.04 (1/24)
+--> Interlaced: false
+--> Interlaced: Top Field First: false
+----------------------------
+----- Audio Attributes -----
+----------------------------
+--> Audio Codec: libvorbis
+--> Audio Bit Rate: 188 kb/s
+--> Sample Rate: 44100 Hz
+--> # of Channels: 2
+--> Channel Layout: 3
+--> Audio Stream Index: -1
+--> Audio Timebase: 1.00 (1/1)
+----------------------------)");
+
+ // Store the DisplayInfo() text in 'output'
+ std::stringstream output;
+ w.DisplayInfo(&output);
+
+ w.Close();
+
+ // Compare a [0, expected.size()) substring of output to expected
+ auto compare_value = output.str().compare(0, expected.size(), expected);
+ CHECK(compare_value == 0);
+}
diff --git a/tests/Fraction.cpp b/tests/Fraction.cpp
index 8736abaf..57d37a79 100644
--- a/tests/Fraction.cpp
+++ b/tests/Fraction.cpp
@@ -32,6 +32,10 @@
#include "Fraction.h"
+#include