2013-09-12 23:41:49 -05:00
|
|
|
|
/**
|
|
|
|
|
|
* @file
|
2025-06-06 15:33:04 -05:00
|
|
|
|
* @brief Example application showing how to attach VideoCacheThread to an FFmpegReader
|
2013-09-12 23:41:49 -05:00
|
|
|
|
* @author Jonathan Thomas <jonathan@openshot.org>
|
|
|
|
|
|
*
|
2019-06-09 08:31:04 -04:00
|
|
|
|
* @ref License
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2025-06-06 15:33:04 -05:00
|
|
|
|
// Copyright (c) 2008-2025 OpenShot Studios, LLC
|
2021-10-16 01:26:26 -04:00
|
|
|
|
//
|
|
|
|
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
2011-10-11 08:44:27 -05:00
|
|
|
|
|
2025-06-04 17:19:01 -05:00
|
|
|
|
#include <chrono>
|
2011-10-11 08:44:27 -05:00
|
|
|
|
#include <iostream>
|
2017-08-20 17:37:39 -05:00
|
|
|
|
#include <memory>
|
2021-03-31 19:35:58 -04:00
|
|
|
|
#include "Frame.h"
|
|
|
|
|
|
#include "FFmpegReader.h"
|
2025-06-05 19:38:53 -05:00
|
|
|
|
#include "FFmpegWriter.h"
|
2025-06-06 15:33:04 -05:00
|
|
|
|
#include "Timeline.h"
|
|
|
|
|
|
#include "Qt/VideoCacheThread.h" // <— your new header
|
2013-11-17 15:12:08 -06:00
|
|
|
|
|
2011-10-11 08:44:27 -05:00
|
|
|
|
using namespace openshot;
|
|
|
|
|
|
|
2017-08-01 01:19:07 -05:00
|
|
|
|
int main(int argc, char* argv[]) {
|
Improved Profile Class (Helper methods, Sortable, Unit tests) (#895)
* Removing legacy profile property. Add new operators for Profile classes (for comparison). Also added new functions to generate different variations of the Profile data (key, short name, long name, long name w/description).
* Add empty constructor for Profile class, and new Profile unit tets
* Adding zero padding to profile Key function, for easier sorting: 01920x1080i2997_16:09
* Clear setfill flag after creating Key() output
* Updating example exe to load an *.osp project file via C++, which makes debugging complex broken projects much easier.
* - Add new unit test to FFmpegWriter to create an animated GIF and verify it can be wrapped with a FrameMapper (with no audio track)
- Improve FrameMapper to ignore missing audio data (i.e. when no audio samples present, don't try and find them or resample them)
* Fix some whitespace issues
* Fix inline documentation mistype
* Fixed missing reuse licensing on new example profile files
* Changing Profile::Key() format to exclude the : character, since Windows file names cannot contain that
* - Large memory leak fixed in FFmpegWriter when closing the video & audio contexts
- Reducing # of cached frames and rescalers to 1, since we no longer use OMP and this is unneeded - we need to refactor much of this code out eventually
* - Fixing whitespace issues
- Code clean-up / line wrapping / etc...
2023-02-02 16:29:38 -06:00
|
|
|
|
|
2025-06-05 19:38:53 -05:00
|
|
|
|
|
2025-06-06 15:33:04 -05:00
|
|
|
|
// 1) Open the FFmpegReader as usual
|
|
|
|
|
|
const char* input_path = "/home/jonathan/Downloads/openshot-testing/sintel_trailer-720p.mp4";
|
|
|
|
|
|
FFmpegReader reader(input_path);
|
|
|
|
|
|
reader.Open();
|
2025-06-05 19:38:53 -05:00
|
|
|
|
|
2025-06-06 15:33:04 -05:00
|
|
|
|
const int64_t total_frames = reader.info.video_length;
|
|
|
|
|
|
std::cout << "Total frames: " << total_frames << "\n";
|
2025-06-05 19:38:53 -05:00
|
|
|
|
|
|
|
|
|
|
|
2025-06-06 15:33:04 -05:00
|
|
|
|
|
|
|
|
|
|
Timeline timeline(reader.info.width, reader.info.height, reader.info.fps, reader.info.sample_rate, reader.info.channels, reader.info.channel_layout);
|
|
|
|
|
|
Clip c1(&reader);
|
|
|
|
|
|
timeline.AddClip(&c1);
|
|
|
|
|
|
timeline.Open();
|
|
|
|
|
|
timeline.DisplayInfo();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2) Construct a VideoCacheThread around 'reader' and start its background loop
|
|
|
|
|
|
// (VideoCacheThread inherits juce::Thread)
|
|
|
|
|
|
std::shared_ptr<VideoCacheThread> cache = std::make_shared<VideoCacheThread>();
|
|
|
|
|
|
cache->Reader(&timeline); // attaches the FFmpegReader and internally calls Play()
|
|
|
|
|
|
cache->StartThread(); // juce::Thread method, begins run()
|
|
|
|
|
|
|
|
|
|
|
|
// 3) Set up the writer exactly as before
|
|
|
|
|
|
FFmpegWriter writer("/home/jonathan/Downloads/performance‐cachetest.mp4");
|
|
|
|
|
|
writer.SetAudioOptions("aac", 48000, 192000);
|
|
|
|
|
|
writer.SetVideoOptions("libx264", 1280, 720, Fraction(30, 1), 5000000);
|
|
|
|
|
|
writer.Open();
|
|
|
|
|
|
|
|
|
|
|
|
// 4) Forward pass: for each frame 1…N, tell the cache thread to seek to that frame,
|
|
|
|
|
|
// then immediately call cache->GetFrame(frame), which will block only if that frame
|
|
|
|
|
|
// hasn’t been decoded into the cache yet.
|
2025-06-04 17:19:01 -05:00
|
|
|
|
auto t0 = std::chrono::high_resolution_clock::now();
|
2025-06-06 15:33:04 -05:00
|
|
|
|
cache->setSpeed(1);
|
|
|
|
|
|
for (int64_t f = 1; f <= total_frames; ++f) {
|
|
|
|
|
|
float pct = (float(f) / total_frames) * 100.0f;
|
|
|
|
|
|
std::cout << "Forward: requesting frame " << f << " (" << pct << "%)\n";
|
|
|
|
|
|
|
|
|
|
|
|
cache->Seek(f); // signal “I need frame f now (and please prefetch f+1, f+2, …)”
|
|
|
|
|
|
std::shared_ptr<Frame> framePtr = timeline.GetFrame(f);
|
|
|
|
|
|
writer.WriteFrame(framePtr);
|
Improved Profile Class (Helper methods, Sortable, Unit tests) (#895)
* Removing legacy profile property. Add new operators for Profile classes (for comparison). Also added new functions to generate different variations of the Profile data (key, short name, long name, long name w/description).
* Add empty constructor for Profile class, and new Profile unit tets
* Adding zero padding to profile Key function, for easier sorting: 01920x1080i2997_16:09
* Clear setfill flag after creating Key() output
* Updating example exe to load an *.osp project file via C++, which makes debugging complex broken projects much easier.
* - Add new unit test to FFmpegWriter to create an animated GIF and verify it can be wrapped with a FrameMapper (with no audio track)
- Improve FrameMapper to ignore missing audio data (i.e. when no audio samples present, don't try and find them or resample them)
* Fix some whitespace issues
* Fix inline documentation mistype
* Fixed missing reuse licensing on new example profile files
* Changing Profile::Key() format to exclude the : character, since Windows file names cannot contain that
* - Large memory leak fixed in FFmpegWriter when closing the video & audio contexts
- Reducing # of cached frames and rescalers to 1, since we no longer use OMP and this is unneeded - we need to refactor much of this code out eventually
* - Fixing whitespace issues
- Code clean-up / line wrapping / etc...
2023-02-02 16:29:38 -06:00
|
|
|
|
}
|
2025-06-04 17:19:01 -05:00
|
|
|
|
auto t1 = std::chrono::high_resolution_clock::now();
|
|
|
|
|
|
auto forward_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0).count();
|
2018-03-04 03:10:59 -06:00
|
|
|
|
|
2025-06-06 15:33:04 -05:00
|
|
|
|
// 5) Backward pass: same idea in reverse
|
2025-06-04 17:19:01 -05:00
|
|
|
|
auto t2 = std::chrono::high_resolution_clock::now();
|
2025-06-06 15:33:04 -05:00
|
|
|
|
cache->setSpeed(-1);
|
|
|
|
|
|
for (int64_t f = total_frames; f >= 1; --f) {
|
|
|
|
|
|
float pct = (float(total_frames - f + 1) / total_frames) * 100.0f;
|
|
|
|
|
|
std::cout << "Backward: requesting frame " << f << " (" << pct << "%)\n";
|
|
|
|
|
|
|
|
|
|
|
|
cache->Seek(f);
|
|
|
|
|
|
std::shared_ptr<Frame> framePtr = timeline.GetFrame(f);
|
|
|
|
|
|
writer.WriteFrame(framePtr);
|
2025-06-04 17:19:01 -05:00
|
|
|
|
}
|
|
|
|
|
|
auto t3 = std::chrono::high_resolution_clock::now();
|
|
|
|
|
|
auto backward_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t3 - t2).count();
|
|
|
|
|
|
|
2025-06-06 15:33:04 -05:00
|
|
|
|
std::cout << "\nForward pass elapsed: " << forward_ms << " ms\n";
|
2025-06-04 17:19:01 -05:00
|
|
|
|
std::cout << "Backward pass elapsed: " << backward_ms << " ms\n";
|
|
|
|
|
|
|
2025-06-06 15:33:04 -05:00
|
|
|
|
// 6) Shut down the cache thread, close everything
|
|
|
|
|
|
cache->StopThread(10000); // politely tells run() to exit, waits up to 10s
|
|
|
|
|
|
reader.Close();
|
|
|
|
|
|
writer.Close();
|
|
|
|
|
|
timeline.Close();
|
2025-06-04 17:19:01 -05:00
|
|
|
|
return 0;
|
2019-08-05 02:54:59 -04:00
|
|
|
|
}
|