Skip to content

Commit 8b12c1f

Browse files
committed
Replacing WriteFrame() method with custom constructor which can accept a CacheBase* pointer, for instances where a DummyReader needs some specific test Frame objects
1 parent d29027a commit 8b12c1f

File tree

3 files changed

+96
-59
lines changed

3 files changed

+96
-59
lines changed

include/DummyReader.h

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,14 @@ namespace openshot
4848
/**
4949
* @brief This class is used as a simple, dummy reader, which can be very useful when writing
5050
* unit tests. It can return a single blank frame or it can return custom frame objects
51-
* which were added using the WriteFrame() method.
51+
* which were passed into the constructor with a Cache object.
5252
*
5353
* A dummy reader can be created with any framerate or samplerate. This is useful in unit
5454
* tests that need to test different framerates or samplerates.
5555
*
5656
* @code
57-
* // Create a reader (Fraction fps, int width, int height, int sample_rate, int channels, float duration)
58-
* openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0);
59-
* r.Open(); // Open the reader
60-
*
61-
* // Get a frame (which will be blank, since we haven't added any frames yet)
62-
* std::shared_ptr<openshot::Frame> f = r.GetFrame(1);
57+
* // Create cache object to store fake Frame objects
58+
* CacheMemory cache;
6359
*
6460
* // Now let's create some test frames
6561
* for (int64_t frame_number = 1; frame_number <= 30; frame_number++)
@@ -82,25 +78,33 @@ namespace openshot
8278
* f->AddAudio(true, 0, 0, audio_buffer, sample_count, 1.0); // add channel 1
8379
* f->AddAudio(true, 1, 0, audio_buffer, sample_count, 1.0); // add channel 2
8480
*
85-
* // Write test frame to dummy reader
86-
* r.WriteFrame(f);
81+
* // Add test frame to cache
82+
* cache.Add(f);
8783
* }
8884
*
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+
*
8989
* // Now let's verify our DummyReader works
9090
* std::shared_ptr<openshot::Frame> f = r.GetFrame(1);
9191
* // r.GetFrame(1)->GetAudioSamples(0)[1] should equal 1.00068033 based on our above calculations
9292
*
93-
* // Close the reader
93+
* // Clean up
9494
* r.Close();
95+
* cache.Clear()
9596
* @endcode
9697
*/
9798
class DummyReader : public ReaderBase
9899
{
99100
private:
100-
CacheMemory dummy_cache;
101+
CacheBase* dummy_cache;
101102
std::shared_ptr<openshot::Frame> image_frame;
102103
bool is_open;
103104

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

106110
/// Blank constructor for DummyReader, with default settings.
@@ -109,6 +113,9 @@ namespace openshot
109113
/// Constructor for DummyReader.
110114
DummyReader(openshot::Fraction fps, int width, int height, int sample_rate, int channels, float duration);
111115

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+
112119
virtual ~DummyReader();
113120

114121
/// Close File
@@ -138,10 +145,6 @@ namespace openshot
138145

139146
/// Open File - which is called by the constructor automatically
140147
void Open() override;
141-
142-
/// @brief Add a frame to the dummy reader. This is useful when constructing unit tests that require custom frames.
143-
/// @param frame The openshot::Frame object to write to this image
144-
void WriteFrame(std::shared_ptr<openshot::Frame> frame);
145148
};
146149

147150
}

src/DummyReader.cpp

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,8 @@
3232

3333
using namespace openshot;
3434

35-
// Blank constructor for DummyReader, with default settings.
36-
DummyReader::DummyReader() {
37-
38-
// Call actual constructor with default values
39-
DummyReader(Fraction(24,1), 1280, 768, 44100, 2, 30.0);
40-
}
41-
42-
// Constructor for DummyReader. Pass a framerate and samplerate.
43-
DummyReader::DummyReader(Fraction fps, int width, int height, int sample_rate, int channels, float duration) {
44-
35+
// Initialize variables used by constructor
36+
void DummyReader::init(Fraction fps, int width, int height, int sample_rate, int channels, float duration) {
4537
// Set key info settings
4638
info.has_audio = false;
4739
info.has_video = true;
@@ -68,10 +60,30 @@ DummyReader::DummyReader(Fraction fps, int width, int height, int sample_rate, i
6860
// Set the ratio based on the reduced fraction
6961
info.display_ratio.num = size.num;
7062
info.display_ratio.den = size.den;
63+
}
64+
65+
// Blank constructor for DummyReader, with default settings.
66+
DummyReader::DummyReader() : dummy_cache(NULL), is_open(false) {
67+
68+
// Initialize important variables
69+
init(Fraction(24,1), 1280, 768, 44100, 2, 30.0);
70+
}
71+
72+
// Constructor for DummyReader. Pass a framerate and samplerate.
73+
DummyReader::DummyReader(Fraction fps, int width, int height, int sample_rate, int channels, float duration) : dummy_cache(NULL), is_open(false) {
74+
75+
// Initialize important variables
76+
init(fps, width, height, sample_rate, channels, duration);
77+
}
7178

72-
// Open and Close the reader, to populate its attributes (such as height, width, etc...)
73-
Open();
74-
Close();
79+
// Constructor which also takes a cache object
80+
DummyReader::DummyReader(Fraction fps, int width, int height, int sample_rate, int channels, float duration, CacheBase* cache) : is_open(false) {
81+
82+
// Initialize important variables
83+
init(fps, width, height, sample_rate, channels, duration);
84+
85+
// Set cache object
86+
dummy_cache = (CacheBase*) cache;
7587
}
7688

7789
DummyReader::~DummyReader() {
@@ -99,48 +111,42 @@ void DummyReader::Close()
99111
{
100112
// Mark as "closed"
101113
is_open = false;
102-
103-
// Clear cache
104-
dummy_cache.Clear();
105-
}
106-
}
107-
108-
// Add Frame objects to DummyReader
109-
void DummyReader::WriteFrame(std::shared_ptr<openshot::Frame> frame)
110-
{
111-
if (frame) {
112-
dummy_cache.Add(frame);
113114
}
114115
}
115116

116117
// Get an openshot::Frame object for a specific frame number of this reader. It is either a blank frame
117-
// or a custom frame added with the WriteFrame() method.
118+
// or a custom frame added with passing a Cache object to the constructor.
118119
std::shared_ptr<Frame> DummyReader::GetFrame(int64_t requested_frame)
119120
{
120121
// Check for open reader (or throw exception)
121122
if (!is_open)
122123
throw ReaderClosed("The ImageReader is closed. Call Open() before calling this method.", "dummy");
123124

124-
if (dummy_cache.Count() == 0 && image_frame) {
125+
int dummy_cache_count = 0;
126+
if (dummy_cache) {
127+
dummy_cache_count = dummy_cache->Count();
128+
}
129+
130+
if (dummy_cache_count == 0 && image_frame) {
125131
// Create a scoped lock, allowing only a single thread to run the following code at one time
126132
const GenericScopedLock<CriticalSection> lock(getFrameCriticalSection);
127133

128134
// Always return same frame (regardless of which frame number was requested)
129135
image_frame->number = requested_frame;
130136
return image_frame;
131137

132-
} else if (dummy_cache.Count() > 0) {
138+
} else if (dummy_cache_count > 0) {
133139
// Create a scoped lock, allowing only a single thread to run the following code at one time
134140
const GenericScopedLock<CriticalSection> lock(getFrameCriticalSection);
135141

136142
// Get a frame from the dummy cache
137-
std::shared_ptr<openshot::Frame> f = dummy_cache.GetFrame(requested_frame);
143+
std::shared_ptr<openshot::Frame> f = dummy_cache->GetFrame(requested_frame);
138144
if (f) {
139145
// return frame from cache (if found)
140146
return f;
141147
} else {
142148
// No cached frame found
143-
throw InvalidFile("Requested frame not found. You can only access Frame numbers added with WriteFrame().", "dummy");
149+
throw InvalidFile("Requested frame not found. You can only access Frame numbers that exist in the Cache object.", "dummy");
144150
}
145151
}
146152
else

tests/DummyReader_Tests.cpp

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,24 @@
3737
using namespace std;
3838
using namespace openshot;
3939

40+
TEST (DummyReader_Basic_Constructor) {
41+
// Create a default fraction (should be 1/1)
42+
openshot::DummyReader r;
43+
r.Open(); // Open the reader
44+
45+
// Check values
46+
CHECK_EQUAL(1280, r.info.width);
47+
CHECK_EQUAL(768, r.info.height);
48+
CHECK_EQUAL(24, r.info.fps.num);
49+
CHECK_EQUAL(1, r.info.fps.den);
50+
CHECK_EQUAL(44100, r.info.sample_rate);
51+
CHECK_EQUAL(2, r.info.channels);
52+
CHECK_EQUAL(30.0, r.info.duration);
53+
}
54+
4055
TEST (DummyReader_Constructor) {
4156
// Create a default fraction (should be 1/1)
42-
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0);
57+
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 60.0);
4358
r.Open(); // Open the reader
4459

4560
// Check values
@@ -49,25 +64,25 @@ TEST (DummyReader_Constructor) {
4964
CHECK_EQUAL(1, r.info.fps.den);
5065
CHECK_EQUAL(44100, r.info.sample_rate);
5166
CHECK_EQUAL(2, r.info.channels);
52-
CHECK_EQUAL(30.0, r.info.duration);
67+
CHECK_EQUAL(60.0, r.info.duration);
5368
}
5469

5570
TEST (DummyReader_Blank_Frame) {
5671
// Create a default fraction (should be 1/1)
5772
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0);
5873
r.Open(); // Open the reader
5974

60-
// Get a blank frame (because we have not added any frames using WriteFrame() yet)
75+
// Get a blank frame (because we have not passed a Cache object (full of Frame objects) to the constructor
6176
// Check values
6277
CHECK_EQUAL(1, r.GetFrame(1)->number);
6378
CHECK_EQUAL(1, r.GetFrame(1)->GetPixels(700)[700] == 0); // black pixel
6479
CHECK_EQUAL(1, r.GetFrame(1)->GetPixels(701)[701] == 0); // black pixel
6580
}
6681

6782
TEST (DummyReader_Fake_Frame) {
68-
// Create a default fraction (should be 1/1)
69-
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0);
70-
r.Open(); // Open the reader
83+
84+
// Create cache object to hold test frames
85+
CacheMemory cache;
7186

7287
// Let's create some test frames
7388
for (int64_t frame_number = 1; frame_number <= 30; frame_number++) {
@@ -87,10 +102,14 @@ TEST (DummyReader_Fake_Frame) {
87102
f->AddAudio(true, 0, 0, audio_buffer, sample_count, 1.0); // add channel 1
88103
f->AddAudio(true, 1, 0, audio_buffer, sample_count, 1.0); // add channel 2
89104

90-
// Write test frame to dummy reader
91-
r.WriteFrame(f);
105+
// Add test frame to dummy reader
106+
cache.Add(f);
92107
}
93108

109+
// Create a default fraction (should be 1/1)
110+
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0, &cache);
111+
r.Open(); // Open the reader
112+
94113
// Verify our artificial audio sample data is correct
95114
CHECK_EQUAL(1, r.GetFrame(1)->number);
96115
CHECK_EQUAL(1, r.GetFrame(1)->GetAudioSamples(0)[0]);
@@ -99,23 +118,32 @@ TEST (DummyReader_Fake_Frame) {
99118
CHECK_EQUAL(2, r.GetFrame(2)->GetAudioSamples(0)[0]);
100119
CHECK_CLOSE(2.00068033, r.GetFrame(2)->GetAudioSamples(0)[1], 0.00001);
101120
CHECK_CLOSE(2.00136054, r.GetFrame(2)->GetAudioSamples(0)[2], 0.00001);
121+
122+
// Clean up
123+
cache.Clear();
124+
r.Close();
102125
}
103126

104127
TEST (DummyReader_Invalid_Fake_Frame) {
105-
// Create a default fraction (should be 1/1)
106-
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0);
107-
r.Open();
108-
109128
// Create fake frames (with specific frame #, samples, and channels)
110129
std::shared_ptr<openshot::Frame> f1(new openshot::Frame(1, 1470, 2));
111130
std::shared_ptr<openshot::Frame> f2(new openshot::Frame(2, 1470, 2));
112131

113-
// Write test frames to dummy reader
114-
r.WriteFrame(f1);
115-
r.WriteFrame(f2);
132+
// Add test frames to cache object
133+
CacheMemory cache;
134+
cache.Add(f1);
135+
cache.Add(f2);
136+
137+
// Create a default fraction (should be 1/1)
138+
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0, &cache);
139+
r.Open();
116140

117141
// Verify exception
118142
CHECK_EQUAL(1, r.GetFrame(1)->number);
119143
CHECK_EQUAL(2, r.GetFrame(2)->number);
120144
CHECK_THROW(r.GetFrame(3)->number, InvalidFile);
145+
146+
// Clean up
147+
cache.Clear();
148+
r.Close();
121149
}

0 commit comments

Comments
 (0)