Skip to content

Commit

Permalink
Merge branch 'develop' into fix-doc-comments
Browse files Browse the repository at this point in the history
  • Loading branch information
ferdnyc committed Mar 31, 2021
2 parents 9eb1e08 + 3f9b402 commit c723ee1
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 51 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
@@ -1,4 +1,4 @@
name: CI Build
name: libopenshot CI Build
on: [push, pull_request]
jobs:
build:
Expand All @@ -13,6 +13,8 @@ jobs:

steps:
- uses: actions/checkout@v2
# Work around a codecov issue detecting commit SHAs
# see: https://community.codecov.io/t/issue-detecting-commit-sha-please-run-actions-checkout-with-fetch-depth-1-or-set-to-0/2571
with:
fetch-depth: 0

Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -4,7 +4,7 @@ solutions to the world.

## Build Status

[![Build Status](https://img.shields.io/travis/OpenShot/libopenshot/develop.svg?label=libopenshot)](https://travis-ci.org/OpenShot/libopenshot) [![Build Status](https://img.shields.io/travis/OpenShot/libopenshot-audio/develop.svg?label=libopenshot-audio)](https://travis-ci.org/OpenShot/libopenshot-audio)
[![libopenshot CI Build](https://github.com/OpenShot/libopenshot/actions/workflows/ci.yml/badge.svg)](https://github.com/OpenShot/libopenshot/actions/workflows/ci.yml) [![libopenshot-audio CI Build](https://github.com/OpenShot/libopenshot-audio/actions/workflows/ci.yml/badge.svg)](https://github.com/OpenShot/libopenshot-audio/actions/workflows/ci.yml)

## Features

Expand Down
8 changes: 4 additions & 4 deletions src/FFmpegReader.cpp
Expand Up @@ -1243,13 +1243,13 @@ void FFmpegReader::ProcessVideoPacket(int64_t requested_frame) {
processing_video_frames[current_frame] = current_frame;

// Create variables for a RGB Frame (since most videos are not in RGB, we must convert it)
AVFrame *pFrameRGB = NULL;
uint8_t *buffer = NULL;
AVFrame *pFrameRGB = nullptr;
uint8_t *buffer = nullptr;

// Allocate an AVFrame structure
pFrameRGB = AV_ALLOCATE_FRAME();
if (pFrameRGB == NULL)
throw OutOfBoundsFrame("Convert Image Broke!", current_frame, video_length);
if (pFrameRGB == nullptr)
throw OutOfMemory("Failed to allocate frame buffer", path);

// Determine the max size of this source image (based on the timeline's size, the scaling mode,
// and the scaling keyframes). This is a performance improvement, to keep the images as small as possible,
Expand Down
32 changes: 19 additions & 13 deletions src/effects/ChromaKey.cpp
Expand Up @@ -83,18 +83,24 @@ std::shared_ptr<openshot::Frame> ChromaKey::GetFrame(std::shared_ptr<openshot::F
for (int pixel = 0, byte_index=0; pixel < image->width() * image->height(); pixel++, byte_index+=4)
{
// Get the RGB values from the pixel
unsigned char R = pixels[byte_index];
unsigned char G = pixels[byte_index + 1];
unsigned char B = pixels[byte_index + 2];
unsigned char A = pixels[byte_index + 3];

// Get distance between mask color and pixel color
long distance = Color::GetDistance((long)R, (long)G, (long)B, mask_R, mask_G, mask_B);

// Alpha out the pixel (if color similar)
if (distance <= threshold)
// MATCHED - Make pixel transparent
pixels[byte_index + 3] = 0;
// Remove the premultiplied alpha values from R,G,B
float A = float(pixels[byte_index + 3]);
unsigned char R = (pixels[byte_index] / A) * 255.0;
unsigned char G = (pixels[byte_index + 1] / A) * 255.0;
unsigned char B = (pixels[byte_index + 2] / A) * 255.0;

// Get distance between mask color and pixel color
long distance = Color::GetDistance((long)R, (long)G, (long)B, mask_R, mask_G, mask_B);

if (distance <= threshold) {
// MATCHED - Make pixel transparent
// Due to premultiplied alpha, we must also zero out
// the individual color channels (or else artifacts are left behind)
pixels[byte_index] = 0;
pixels[byte_index + 1] = 0;
pixels[byte_index + 2] = 0;
pixels[byte_index + 3] = 0;
}
}

// return the modified frame
Expand Down Expand Up @@ -168,7 +174,7 @@ std::string ChromaKey::PropertiesJSON(int64_t requested_frame) const {
root["color"]["red"] = add_property_json("Red", color.red.GetValue(requested_frame), "float", "", &color.red, 0, 255, false, requested_frame);
root["color"]["blue"] = add_property_json("Blue", color.blue.GetValue(requested_frame), "float", "", &color.blue, 0, 255, false, requested_frame);
root["color"]["green"] = add_property_json("Green", color.green.GetValue(requested_frame), "float", "", &color.green, 0, 255, false, requested_frame);
root["fuzz"] = add_property_json("Fuzz", fuzz.GetValue(requested_frame), "float", "", &fuzz, 0, 25, false, requested_frame);
root["fuzz"] = add_property_json("Fuzz", fuzz.GetValue(requested_frame), "float", "", &fuzz, 0, 125, false, requested_frame);

// Return formatted string
return root.toStyledString();
Expand Down
101 changes: 69 additions & 32 deletions tests/DummyReader_Tests.cpp
Expand Up @@ -40,43 +40,48 @@
#include "Fraction.h"
#include "Frame.h"

using namespace std;
using namespace openshot;
SUITE (DummyReader) {

TEST (DummyReader_Basic_Constructor) {
// Create a default fraction (should be 1/1)
TEST (Default_Constructor) {
openshot::DummyReader r;
r.Open(); // Open the reader

// Check values
CHECK_EQUAL(1280, r.info.width);
CHECK_EQUAL(768, r.info.height);
CHECK_EQUAL(24, r.info.fps.num);
CHECK_EQUAL(1, r.info.fps.den);
CHECK_EQUAL(44100, r.info.sample_rate);
CHECK_EQUAL(2, r.info.channels);
CHECK_EQUAL(30.0, r.info.duration);
CHECK_EQUAL(false, r.IsOpen());
CHECK_THROW(r.GetFrame(1), openshot::ReaderClosed);

r.Open();

// Default values
CHECK_EQUAL(1280, r.info.width);
CHECK_EQUAL(768, r.info.height);
CHECK_EQUAL(24, r.info.fps.num);
CHECK_EQUAL(1, r.info.fps.den);
CHECK_EQUAL(44100, r.info.sample_rate);
CHECK_EQUAL(2, r.info.channels);
CHECK_EQUAL(30.0, r.info.duration);

CHECK_EQUAL("DummyReader", r.Name());

auto cache = r.GetCache();
CHECK_EQUAL(true, cache == nullptr);
}

TEST (DummyReader_Constructor) {
// Create a default fraction (should be 1/1)
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 60.0);
r.Open(); // Open the reader
TEST (Constructor) {
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 48000, 2, 60.0);
r.Open();

// Check values
CHECK_EQUAL(1920, r.info.width);
CHECK_EQUAL(1080, r.info.height);
CHECK_EQUAL(30, r.info.fps.num);
CHECK_EQUAL(1, r.info.fps.den);
CHECK_EQUAL(44100, r.info.sample_rate);
CHECK_EQUAL(48000, r.info.sample_rate);
CHECK_EQUAL(2, r.info.channels);
CHECK_EQUAL(60.0, r.info.duration);
}

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

// Get a blank frame (because we have not passed a Cache object (full of Frame objects) to the constructor
// Check values
Expand All @@ -85,17 +90,17 @@ TEST (DummyReader_Blank_Frame) {
CHECK_EQUAL(1, r.GetFrame(1)->GetPixels(701)[701] == 0); // black pixel
}

TEST (DummyReader_Fake_Frame) {
TEST (Fake_Frame) {

// Create cache object to hold test frames
CacheMemory cache;
openshot::CacheMemory cache;

// Let's create some test frames
for (int64_t frame_number = 1; frame_number <= 30; frame_number++) {
// Create blank frame (with specific frame #, samples, and channels)
// Sample count should be 44100 / 30 fps = 1470 samples per frame
int sample_count = 1470;
std::shared_ptr<openshot::Frame> f(new openshot::Frame(frame_number, sample_count, 2));
auto f = std::make_shared<openshot::Frame>(frame_number, sample_count, 2);

// Create test samples with incrementing value
float *audio_buffer = new float[sample_count];
Expand All @@ -112,9 +117,8 @@ TEST (DummyReader_Fake_Frame) {
cache.Add(f);
}

// Create a default fraction (should be 1/1)
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0, &cache);
r.Open(); // Open the reader
r.Open();

// Verify our artificial audio sample data is correct
CHECK_EQUAL(1, r.GetFrame(1)->number);
Expand All @@ -130,26 +134,59 @@ TEST (DummyReader_Fake_Frame) {
r.Close();
}

TEST (DummyReader_Invalid_Fake_Frame) {
TEST (Invalid_Fake_Frame) {
// Create fake frames (with specific frame #, samples, and channels)
std::shared_ptr<openshot::Frame> f1(new openshot::Frame(1, 1470, 2));
std::shared_ptr<openshot::Frame> f2(new openshot::Frame(2, 1470, 2));
auto f1 = std::make_shared<openshot::Frame>(1, 1470, 2);
auto f2 = std::make_shared<openshot::Frame>(2, 1470, 2);

// Add test frames to cache object
CacheMemory cache;
openshot::CacheMemory cache;
cache.Add(f1);
cache.Add(f2);

// Create a default fraction (should be 1/1)
openshot::DummyReader r(openshot::Fraction(30, 1), 1920, 1080, 44100, 2, 30.0, &cache);
r.Open();

// Verify exception
CHECK_EQUAL(1, r.GetFrame(1)->number);
CHECK_EQUAL(2, r.GetFrame(2)->number);
CHECK_THROW(r.GetFrame(3)->number, InvalidFile);
CHECK_THROW(r.GetFrame(3)->number, openshot::InvalidFile);

// Clean up
cache.Clear();
r.Close();
}


TEST(Json)
{
openshot::DummyReader r1;
openshot::DummyReader r2(openshot::Fraction(24, 1), 1280, 768, 44100, 2, 30.0);
auto json1 = r1.Json();
auto json2 = r2.JsonValue();
auto json_string2 = json2.toStyledString();
CHECK_EQUAL(json1, json_string2);
}

TEST(SetJson)
{
openshot::DummyReader r1;
std::stringstream json_stream;
json_stream << R"json(
{
"width": 1920,
"height": 1080,
"fps": { "num": 15, "den": 1 },
"duration": 15.0
}
)json";

r1.SetJson(json_stream.str());
CHECK_EQUAL(1920, r1.info.width);
CHECK_EQUAL(1080, r1.info.height);
CHECK_EQUAL(15, r1.info.fps.num);
CHECK_EQUAL(1, r1.info.fps.den);
CHECK_EQUAL(15.0, r1.info.duration);
}

} // SUITE

0 comments on commit c723ee1

Please sign in to comment.