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>
|
2026-02-06 16:46:40 -06:00
|
|
|
#include <string>
|
|
|
|
|
#include "Clip.h"
|
2021-03-31 19:35:58 -04:00
|
|
|
#include "Frame.h"
|
|
|
|
|
#include "FFmpegReader.h"
|
2026-02-06 16:46:40 -06:00
|
|
|
#include "Settings.h"
|
2025-06-06 15:33:04 -05:00
|
|
|
#include "Timeline.h"
|
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[]) {
|
2026-02-06 16:46:40 -06:00
|
|
|
using clock = std::chrono::high_resolution_clock;
|
|
|
|
|
auto total_start = clock::now();
|
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
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
const std::string output_dir = "/home/jonathan/Downloads";
|
|
|
|
|
const std::string input_paths[] = {
|
|
|
|
|
"/home/jonathan/Videos/3.4 Release/Screencasts/Timing.mp4",
|
|
|
|
|
"/home/jonathan/Downloads/openshot-testing/sintel_trailer-720p.mp4"
|
|
|
|
|
};
|
|
|
|
|
const int64_t frames_to_fetch[] = {175, 225, 240, 500, 1000};
|
|
|
|
|
const bool use_hw_decode = false;
|
2025-06-05 19:38:53 -05:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
std::cout << "Hardware decode: " << (use_hw_decode ? "ON" : "OFF") << "\n";
|
|
|
|
|
openshot::Settings::Instance()->HARDWARE_DECODER = use_hw_decode ? 1 : 0;
|
2025-06-05 19:38:53 -05:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
for (const std::string& input_path : input_paths) {
|
|
|
|
|
auto file_start = clock::now();
|
|
|
|
|
std::string base = input_path;
|
|
|
|
|
size_t slash = base.find_last_of('/');
|
|
|
|
|
if (slash != std::string::npos) {
|
|
|
|
|
base = base.substr(slash + 1);
|
|
|
|
|
}
|
2025-06-05 19:38:53 -05:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
std::cout << "\n=== File: " << base << " ===\n";
|
2025-06-05 19:38:53 -05:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
auto t0 = clock::now();
|
|
|
|
|
FFmpegReader reader(input_path.c_str());
|
|
|
|
|
auto t1 = clock::now();
|
|
|
|
|
std::cout << "FFmpegReader ctor: "
|
|
|
|
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0).count()
|
|
|
|
|
<< " ms\n";
|
2025-06-06 15:33:04 -05:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
auto t2 = clock::now();
|
|
|
|
|
reader.Open();
|
|
|
|
|
auto t3 = clock::now();
|
|
|
|
|
std::cout << "FFmpegReader Open(): "
|
|
|
|
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(t3 - t2).count()
|
|
|
|
|
<< " ms\n";
|
2025-06-06 15:33:04 -05:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
auto t4 = clock::now();
|
|
|
|
|
Timeline timeline(1920, 1080, Fraction(30, 1), reader.info.sample_rate, reader.info.channels, reader.info.channel_layout);
|
|
|
|
|
timeline.SetMaxSize(640, 480);
|
|
|
|
|
auto t5 = clock::now();
|
|
|
|
|
std::cout << "Timeline ctor (1080p30): "
|
|
|
|
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(t5 - t4).count()
|
|
|
|
|
<< " ms\n";
|
2025-06-06 15:33:04 -05:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
auto t6 = clock::now();
|
|
|
|
|
Clip c1(&reader);
|
|
|
|
|
auto t7 = clock::now();
|
|
|
|
|
std::cout << "Clip ctor: "
|
|
|
|
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(t7 - t6).count()
|
|
|
|
|
<< " ms\n";
|
2025-06-06 15:33:04 -05:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
timeline.AddClip(&c1);
|
2025-06-06 15:33:04 -05:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
auto t8 = clock::now();
|
|
|
|
|
timeline.Open();
|
|
|
|
|
auto t9 = clock::now();
|
|
|
|
|
std::cout << "Timeline Open(): "
|
|
|
|
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(t9 - t8).count()
|
|
|
|
|
<< " ms\n";
|
2025-06-06 15:33:04 -05:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
for (int64_t frame_number : frames_to_fetch) {
|
|
|
|
|
auto loop_start = clock::now();
|
|
|
|
|
std::cout << "Requesting frame " << frame_number << "...\n";
|
|
|
|
|
|
|
|
|
|
auto t10 = clock::now();
|
|
|
|
|
std::shared_ptr<Frame> frame = timeline.GetFrame(frame_number);
|
|
|
|
|
auto t11 = clock::now();
|
|
|
|
|
std::cout << "Timeline GetFrame(" << frame_number << "): "
|
|
|
|
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(t11 - t10).count()
|
|
|
|
|
<< " ms\n";
|
|
|
|
|
|
|
|
|
|
std::string out_path = output_dir + "/frame-" + base + "-" + std::to_string(frame_number) + ".jpg";
|
|
|
|
|
|
|
|
|
|
auto t12 = clock::now();
|
|
|
|
|
frame->Thumbnail(out_path, 200, 80, "", "", "#000000", false, "JPEG", 95, 0.0f);
|
|
|
|
|
auto t13 = clock::now();
|
|
|
|
|
std::cout << "Frame Thumbnail() JPEG (" << frame_number << "): "
|
|
|
|
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(t13 - t12).count()
|
|
|
|
|
<< " ms\n";
|
|
|
|
|
|
|
|
|
|
auto loop_end = clock::now();
|
|
|
|
|
std::cout << "Frame loop total (" << frame_number << "): "
|
|
|
|
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(loop_end - loop_start).count()
|
|
|
|
|
<< " ms\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reader.Close();
|
|
|
|
|
timeline.Close();
|
|
|
|
|
|
|
|
|
|
auto file_end = clock::now();
|
|
|
|
|
std::cout << "File total (" << base << "): "
|
|
|
|
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(file_end - file_start).count()
|
|
|
|
|
<< " ms\n";
|
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
|
|
|
}
|
2018-03-04 03:10:59 -06:00
|
|
|
|
2026-02-06 16:46:40 -06:00
|
|
|
auto total_end = clock::now();
|
|
|
|
|
std::cout << "Total elapsed: "
|
|
|
|
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(total_end - total_start).count()
|
|
|
|
|
<< " ms\n";
|
2025-06-04 17:19:01 -05:00
|
|
|
return 0;
|
2019-08-05 02:54:59 -04:00
|
|
|
}
|