Skip to content

Commit 07fef5b

Browse files
committed
Merge branch 'develop' into store-qt-version
2 parents 0e79844 + c29174f commit 07fef5b

File tree

14 files changed

+414
-87
lines changed

14 files changed

+414
-87
lines changed

.travis.yml

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,12 @@ addons:
3232
- curl
3333

3434
jobs:
35-
include:
3635

36+
# The FFmpeg 3.2 backport PPA has gone missing
37+
allow_failures:
38+
- name: "FFmpeg 3.2 GCC (Ubuntu 16.04 Xenial)"
39+
40+
include:
3741
- name: "Coverage + FFmpeg 3.4 GCC (Ubuntu 18.04 Bionic)"
3842
env:
3943
- BUILD_VERSION=coverage_ffmpeg34
@@ -45,7 +49,6 @@ jobs:
4549
apt:
4650
sources:
4751
- sourceline: 'ppa:openshot.developers/libopenshot-daily'
48-
- sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic'
4952
packages:
5053
- *p_common
5154
- qt5-default
@@ -54,19 +57,17 @@ jobs:
5457
- lcov
5558
- binutils-common # For c++filt
5659

57-
- name: "FFmpeg 4 GCC (Ubuntu 18.04 Bionic)"
60+
- name: "FFmpeg 4 GCC (Ubuntu 20.04 Focal)"
5861
env:
5962
- BUILD_VERSION=ffmpeg4
6063
- CMAKE_EXTRA_ARGS=""
6164
- TEST_TARGET=test
6265
os: linux
63-
dist: bionic
66+
dist: focal
6467
addons:
6568
apt:
6669
sources:
6770
- sourceline: 'ppa:openshot.developers/libopenshot-daily'
68-
- sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic'
69-
- sourceline: 'ppa:jonathonf/ffmpeg-4'
7071
packages:
7172
- *p_common
7273
- qt5-default
@@ -92,7 +93,6 @@ jobs:
9293
apt:
9394
sources:
9495
- sourceline: 'ppa:openshot.developers/libopenshot-daily'
95-
- sourceline: 'ppa:beineri/opt-qt-5.12.3-bionic'
9696
packages:
9797
- *p_common
9898
- qt5-default
@@ -110,7 +110,6 @@ jobs:
110110
apt:
111111
sources:
112112
- sourceline: 'ppa:openshot.developers/libopenshot-daily'
113-
- sourceline: 'ppa:beineri/opt-qt-5.10.0-xenial'
114113
- sourceline: 'ppa:jon-hedgerows/ffmpeg-backports'
115114
packages:
116115
- *p_common

include/Clip.h

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,11 @@ namespace openshot {
139139
void reverse_buffer(juce::AudioSampleBuffer* buffer);
140140

141141
public:
142-
openshot::GravityType gravity; ///< The gravity of a clip determines where it snaps to its parent
143-
openshot::ScaleType scale; ///< The scale determines how a clip should be resized to fit its parent
144-
openshot::AnchorType anchor; ///< The anchor determines what parent a clip should snap to
145-
openshot::FrameDisplayType display; ///< The format to display the frame number (if any)
146-
openshot::VolumeMixType mixing; ///< What strategy should be followed when mixing audio with other clips
142+
openshot::GravityType gravity; ///< The gravity of a clip determines where it snaps to its parent
143+
openshot::ScaleType scale; ///< The scale determines how a clip should be resized to fit its parent
144+
openshot::AnchorType anchor; ///< The anchor determines what parent a clip should snap to
145+
openshot::FrameDisplayType display; ///< The format to display the frame number (if any)
146+
openshot::VolumeMixType mixing; ///< What strategy should be followed when mixing audio with other clips
147147

148148
/// Default Constructor
149149
Clip();
@@ -207,15 +207,19 @@ namespace openshot {
207207
bool Waveform() { return waveform; } ///< Get the waveform property of this clip
208208
void Waveform(bool value) { waveform = value; } ///< Set the waveform property of this clip
209209

210-
// Scale and Location curves
210+
// Scale, Location, and Alpha curves
211211
openshot::Keyframe scale_x; ///< Curve representing the horizontal scaling in percent (0 to 1)
212212
openshot::Keyframe scale_y; ///< Curve representing the vertical scaling in percent (0 to 1)
213213
openshot::Keyframe location_x; ///< Curve representing the relative X position in percent based on the gravity (-1 to 1)
214214
openshot::Keyframe location_y; ///< Curve representing the relative Y position in percent based on the gravity (-1 to 1)
215-
216-
// Alpha and Rotation curves
217215
openshot::Keyframe alpha; ///< Curve representing the alpha (1 to 0)
216+
217+
// Rotation and Shear curves (origin point (x,y) is adjustable for both rotation and shear)
218218
openshot::Keyframe rotation; ///< Curve representing the rotation (0 to 360)
219+
openshot::Keyframe shear_x; ///< Curve representing X shear angle in degrees (-45.0=left, 45.0=right)
220+
openshot::Keyframe shear_y; ///< Curve representing Y shear angle in degrees (-45.0=down, 45.0=up)
221+
openshot::Keyframe origin_x; ///< Curve representing X origin point (0.0=0% (left), 1.0=100% (right))
222+
openshot::Keyframe origin_y; ///< Curve representing Y origin point (0.0=0% (top), 1.0=100% (bottom))
219223

220224
// Time and Volume curves
221225
openshot::Keyframe time; ///< Curve representing the frames over time to play (used for speed and direction of video)
@@ -231,9 +235,7 @@ namespace openshot {
231235
openshot::Keyframe crop_x; ///< Curve representing X offset in percent (-1.0=-100%, 0.0=0%, 1.0=100%)
232236
openshot::Keyframe crop_y; ///< Curve representing Y offset in percent (-1.0=-100%, 0.0=0%, 1.0=100%)
233237

234-
// Shear and perspective curves
235-
openshot::Keyframe shear_x; ///< Curve representing X shear angle in degrees (-45.0=left, 45.0=right)
236-
openshot::Keyframe shear_y; ///< Curve representing Y shear angle in degrees (-45.0=down, 45.0=up)
238+
// Perspective curves
237239
openshot::Keyframe perspective_c1_x; ///< Curves representing X for coordinate 1
238240
openshot::Keyframe perspective_c1_y; ///< Curves representing Y for coordinate 1
239241
openshot::Keyframe perspective_c2_x; ///< Curves representing X for coordinate 2

include/DummyReader.h

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,65 @@
4646
namespace openshot
4747
{
4848
/**
49-
* @brief This class is used as a simple, dummy reader, which always returns a blank frame.
49+
* @brief This class is used as a simple, dummy reader, which can be very useful when writing
50+
* unit tests. It can return a single blank frame or it can return custom frame objects
51+
* which were passed into the constructor with a Cache object.
5052
*
5153
* A dummy reader can be created with any framerate or samplerate. This is useful in unit
5254
* tests that need to test different framerates or samplerates.
55+
*
56+
* @code
57+
* // Create cache object to store fake Frame objects
58+
* CacheMemory cache;
59+
*
60+
* // Now let's create some test frames
61+
* for (int64_t frame_number = 1; frame_number <= 30; frame_number++)
62+
* {
63+
* // Create blank frame (with specific frame #, samples, and channels)
64+
* // Sample count should be 44100 / 30 fps = 1470 samples per frame
65+
* int sample_count = 1470;
66+
* std::shared_ptr<openshot::Frame> f(new openshot::Frame(frame_number, sample_count, 2));
67+
*
68+
* // Create test samples with incrementing value
69+
* float *audio_buffer = new float[sample_count];
70+
* for (int64_t sample_number = 0; sample_number < sample_count; sample_number++)
71+
* {
72+
* // Generate an incrementing audio sample value (just as an example)
73+
* audio_buffer[sample_number] = float(frame_number) + (float(sample_number) / float(sample_count));
74+
* }
75+
*
76+
* // Add custom audio samples to Frame (bool replaceSamples, int destChannel, int destStartSample, const float* source,
77+
* // int numSamples, float gainToApplyToSource = 1.0f)
78+
* f->AddAudio(true, 0, 0, audio_buffer, sample_count, 1.0); // add channel 1
79+
* f->AddAudio(true, 1, 0, audio_buffer, sample_count, 1.0); // add channel 2
80+
*
81+
* // Add test frame to cache
82+
* cache.Add(f);
83+
* }
84+
*
85+
* // Create a reader (Fraction fps, int width, int height, int sample_rate, int channels, float duration, CacheBase* cache)
86+
* openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0, &cache);
87+
* r.Open(); // Open the reader
88+
*
89+
* // Now let's verify our DummyReader works
90+
* std::shared_ptr<openshot::Frame> f = r.GetFrame(1);
91+
* // r.GetFrame(1)->GetAudioSamples(0)[1] should equal 1.00068033 based on our above calculations
92+
*
93+
* // Clean up
94+
* r.Close();
95+
* cache.Clear()
96+
* @endcode
5397
*/
5498
class DummyReader : public ReaderBase
5599
{
56100
private:
101+
CacheBase* dummy_cache;
57102
std::shared_ptr<openshot::Frame> image_frame;
58103
bool is_open;
59104

105+
/// Initialize variables used by constructor
106+
void init(Fraction fps, int width, int height, int sample_rate, int channels, float duration);
107+
60108
public:
61109

62110
/// Blank constructor for DummyReader, with default settings.
@@ -65,6 +113,9 @@ namespace openshot
65113
/// Constructor for DummyReader.
66114
DummyReader(openshot::Fraction fps, int width, int height, int sample_rate, int channels, float duration);
67115

116+
/// Constructor for DummyReader which takes a frame cache object.
117+
DummyReader(openshot::Fraction fps, int width, int height, int sample_rate, int channels, float duration, CacheBase* cache);
118+
68119
virtual ~DummyReader();
69120

70121
/// Close File

include/FFmpegUtilities.h

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,10 @@
163163
#define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context)
164164
#define AV_GET_CODEC_TYPE(av_stream) av_stream->codecpar->codec_type
165165
#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codecpar->codec_id
166-
auto AV_GET_CODEC_CONTEXT = [](AVStream* av_stream, AVCodec* av_codec) { \
167-
AVCodecContext *context = avcodec_alloc_context3(av_codec); \
168-
avcodec_parameters_to_context(context, av_stream->codecpar); \
169-
return context; \
170-
};
166+
#define AV_GET_CODEC_CONTEXT(av_stream, av_codec) \
167+
({ AVCodecContext *context = avcodec_alloc_context3(av_codec); \
168+
avcodec_parameters_to_context(context, av_stream->codecpar); \
169+
context; })
171170
#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_codec;
172171
#define AV_GET_CODEC_FROM_STREAM(av_stream,codec_in)
173172
#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_stream->codecpar
@@ -199,11 +198,10 @@
199198
#define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context)
200199
#define AV_GET_CODEC_TYPE(av_stream) av_stream->codecpar->codec_type
201200
#define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codecpar->codec_id
202-
auto AV_GET_CODEC_CONTEXT = [](AVStream* av_stream, AVCodec* av_codec) { \
203-
AVCodecContext *context = avcodec_alloc_context3(av_codec); \
204-
avcodec_parameters_to_context(context, av_stream->codecpar); \
205-
return context; \
206-
};
201+
#define AV_GET_CODEC_CONTEXT(av_stream, av_codec) \
202+
({ AVCodecContext *context = avcodec_alloc_context3(av_codec); \
203+
avcodec_parameters_to_context(context, av_stream->codecpar); \
204+
context; })
207205
#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_codec;
208206
#define AV_GET_CODEC_FROM_STREAM(av_stream,codec_in)
209207
#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_stream->codecpar

include/Qt/AudioPlaybackThread.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ namespace openshot
7575
static AudioDeviceManagerSingleton * Instance();
7676

7777
/// Public device manager property
78-
AudioDeviceManager audioDeviceManager;
78+
juce::AudioDeviceManager audioDeviceManager;
7979

8080
/// Close audio device
8181
void CloseAudioDevice();
@@ -86,9 +86,9 @@ namespace openshot
8686
*/
8787
class AudioPlaybackThread : juce::Thread
8888
{
89-
AudioSourcePlayer player;
90-
AudioTransportSource transport;
91-
MixerAudioSource mixer;
89+
juce::AudioSourcePlayer player;
90+
juce::AudioTransportSource transport;
91+
juce::MixerAudioSource mixer;
9292
AudioReaderSource *source;
9393
double sampleRate;
9494
int numChannels;

src/Clip.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ void Clip::init_settings()
8989
// Init shear and perspective curves
9090
shear_x = Keyframe(0.0);
9191
shear_y = Keyframe(0.0);
92+
origin_x = Keyframe(0.5);
93+
origin_y = Keyframe(0.5);
9294
perspective_c1_x = Keyframe(-1.0);
9395
perspective_c1_y = Keyframe(-1.0);
9496
perspective_c2_x = Keyframe(-1.0);
@@ -148,8 +150,11 @@ Clip::Clip(ReaderBase* new_reader) : resampler(NULL), reader(new_reader), alloca
148150
Open();
149151
Close();
150152

151-
// Update duration
152-
End(reader->info.duration);
153+
// Update duration and set parent
154+
if (reader) {
155+
End(reader->info.duration);
156+
reader->SetClip(this);
157+
}
153158
}
154159

155160
// Constructor with filepath
@@ -202,9 +207,10 @@ Clip::Clip(std::string path) : resampler(NULL), reader(NULL), allocated_reader(N
202207
}
203208
}
204209

205-
// Update duration
210+
// Update duration and set parent
206211
if (reader) {
207212
End(reader->info.duration);
213+
reader->SetClip(this);
208214
allocated_reader = reader;
209215
init_reader_rotation();
210216
}
@@ -712,6 +718,8 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const {
712718
root["shear_x"] = add_property_json("Shear X", shear_x.GetValue(requested_frame), "float", "", &shear_x, -1.0, 1.0, false, requested_frame);
713719
root["shear_y"] = add_property_json("Shear Y", shear_y.GetValue(requested_frame), "float", "", &shear_y, -1.0, 1.0, false, requested_frame);
714720
root["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", &rotation, -360, 360, false, requested_frame);
721+
root["origin_x"] = add_property_json("Origin X", origin_x.GetValue(requested_frame), "float", "", &origin_x, 0.0, 1.0, false, requested_frame);
722+
root["origin_y"] = add_property_json("Origin Y", origin_y.GetValue(requested_frame), "float", "", &origin_y, 0.0, 1.0, false, requested_frame);
715723
root["volume"] = add_property_json("Volume", volume.GetValue(requested_frame), "float", "", &volume, 0.0, 1.0, false, requested_frame);
716724
root["time"] = add_property_json("Time", time.GetValue(requested_frame), "float", "", &time, 0.0, 30 * 60 * 60 * 48, false, requested_frame);
717725
root["channel_filter"] = add_property_json("Channel Filter", channel_filter.GetValue(requested_frame), "int", "", &channel_filter, -1, 10, false, requested_frame);
@@ -768,6 +776,8 @@ Json::Value Clip::JsonValue() const {
768776
root["crop_y"] = crop_y.JsonValue();
769777
root["shear_x"] = shear_x.JsonValue();
770778
root["shear_y"] = shear_y.JsonValue();
779+
root["origin_x"] = origin_x.JsonValue();
780+
root["origin_y"] = origin_y.JsonValue();
771781
root["channel_filter"] = channel_filter.JsonValue();
772782
root["channel_mapping"] = channel_mapping.JsonValue();
773783
root["has_audio"] = has_audio.JsonValue();
@@ -865,6 +875,10 @@ void Clip::SetJsonValue(const Json::Value root) {
865875
shear_x.SetJsonValue(root["shear_x"]);
866876
if (!root["shear_y"].isNull())
867877
shear_y.SetJsonValue(root["shear_y"]);
878+
if (!root["origin_x"].isNull())
879+
origin_x.SetJsonValue(root["origin_x"]);
880+
if (!root["origin_y"].isNull())
881+
origin_y.SetJsonValue(root["origin_y"]);
868882
if (!root["channel_filter"].isNull())
869883
channel_filter.SetJsonValue(root["channel_filter"]);
870884
if (!root["channel_mapping"].isNull())

0 commit comments

Comments
 (0)