You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
* 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...
236 lines
5.5 KiB
C++
236 lines
5.5 KiB
C++
/**
|
|
* @file
|
|
* @brief Unit tests for openshot::FFmpegWriter
|
|
* @author Jonathan Thomas <jonathan@openshot.org>
|
|
*
|
|
* @ref License
|
|
*/
|
|
|
|
// Copyright (c) 2008-2019 OpenShot Studios, LLC
|
|
//
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
#include <sstream>
|
|
#include <memory>
|
|
|
|
#include "openshot_catch.h"
|
|
|
|
#include "FFmpegWriter.h"
|
|
#include "Exceptions.h"
|
|
#include "FFmpegReader.h"
|
|
#include "Fraction.h"
|
|
#include "Frame.h"
|
|
#include "Timeline.h"
|
|
|
|
using namespace std;
|
|
using namespace openshot;
|
|
|
|
TEST_CASE( "Webm", "[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();
|
|
|
|
// Write some frames
|
|
w.WriteFrame(&r, 24, 50);
|
|
|
|
// Close writer & reader
|
|
w.Close();
|
|
r.Close();
|
|
|
|
FFmpegReader r1("output1.webm");
|
|
r1.Open();
|
|
|
|
// Verify various settings on new MP4
|
|
CHECK(r1.GetFrame(1)->GetAudioChannelsCount() == 2);
|
|
CHECK(r1.info.fps.num == 24);
|
|
CHECK(r1.info.fps.den == 1);
|
|
|
|
// Get a specific frame
|
|
std::shared_ptr<Frame> f = r1.GetFrame(8);
|
|
|
|
// Get the image data for row 500
|
|
const unsigned char* pixels = f->GetPixels(500);
|
|
int pixel_index = 112 * 4; // pixel 112 (4 bytes per pixel)
|
|
|
|
// Check image properties on scanline 10, pixel 112
|
|
CHECK((int)pixels[pixel_index] == Approx(23).margin(5));
|
|
CHECK((int)pixels[pixel_index + 1] == Approx(23).margin(5));
|
|
CHECK((int)pixels[pixel_index + 2] == Approx(23).margin(5));
|
|
CHECK((int)pixels[pixel_index + 3] == Approx(255).margin(5));
|
|
}
|
|
|
|
TEST_CASE( "Options_Overloads", "[libopenshot][ffmpegwriter]" )
|
|
{
|
|
// Reader
|
|
std::stringstream path;
|
|
path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4";
|
|
FFmpegReader r(path.str());
|
|
r.Open();
|
|
|
|
/* WRITER ---------------- */
|
|
FFmpegWriter w("output1.mp4");
|
|
|
|
// Set options
|
|
w.SetAudioOptions("aac", 48000, 192000);
|
|
w.SetVideoOptions("libx264", 1280, 720, Fraction(30,1), 5000000);
|
|
|
|
// Open writer
|
|
w.Open();
|
|
|
|
// Write some frames
|
|
w.WriteFrame(&r, 24, 50);
|
|
|
|
// Close writer & reader
|
|
w.Close();
|
|
r.Close();
|
|
|
|
FFmpegReader r1("output1.mp4");
|
|
r1.Open();
|
|
|
|
// Verify implied settings
|
|
CHECK(r1.info.has_audio == true);
|
|
CHECK(r1.info.has_video == true);
|
|
|
|
CHECK(r1.GetFrame(1)->GetAudioChannelsCount() == 2);
|
|
CHECK(r1.info.channel_layout == LAYOUT_STEREO);
|
|
|
|
CHECK(r1.info.pixel_ratio.num == 1);
|
|
CHECK(r1.info.pixel_ratio.den == 1);
|
|
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
|
|
CHECK(output.str().substr(0, expected.size()) == expected);
|
|
}
|
|
|
|
TEST_CASE( "Gif", "[libopenshot][ffmpegwriter]" )
|
|
{
|
|
// Reader
|
|
std::stringstream path;
|
|
path << TEST_MEDIA_PATH << "sintel_trailer-720p.mp4";
|
|
|
|
// Create Gif Clip
|
|
Clip clip_video(path.str());
|
|
clip_video.Layer(0);
|
|
clip_video.Position(0.0);
|
|
clip_video.Open();
|
|
|
|
// Create Timeline w/ 1 Gif Clip (with 0 sample rate, and 0 channels)
|
|
openshot::Timeline t(1280, 720, Fraction(30,1), 0, 0, LAYOUT_MONO);
|
|
t.AddClip(&clip_video);
|
|
t.Open();
|
|
|
|
/* WRITER ---------------- */
|
|
FFmpegWriter w("output1.gif");
|
|
|
|
// Set options (no audio options are set)
|
|
w.SetVideoOptions(true, "gif", Fraction(24,1), 1280, 720, Fraction(1,1), false, false, 15000000);
|
|
|
|
// Create streams
|
|
w.PrepareStreams();
|
|
|
|
// Open writer
|
|
w.Open();
|
|
|
|
// Write some frames
|
|
w.WriteFrame(&t, 1, 60);
|
|
|
|
// Close writer & reader
|
|
w.Close();
|
|
t.Close();
|
|
|
|
FFmpegReader r1("output1.gif");
|
|
r1.Open();
|
|
|
|
// Verify various settings on new Gif
|
|
CHECK(r1.GetFrame(1)->GetAudioChannelsCount() == 0);
|
|
CHECK(r1.GetFrame(1)->GetAudioSamplesCount() == 0);
|
|
CHECK(r1.info.fps.num == 24);
|
|
CHECK(r1.info.fps.den == 1);
|
|
|
|
// Close reader
|
|
r1.Close();
|
|
}
|