Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ffmpeg compositor native code #2

Merged
merged 35 commits into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0226ded
add bundlex boilerplate
Janix4000 Jul 20, 2022
4a33d0f
create more universal state
Janix4000 Jul 20, 2022
2a16d57
change names
Janix4000 Jul 21, 2022
1cde0a3
base filterr cahnges
Janix4000 Jul 21, 2022
8d89491
update create_filter_description
Janix4000 Jul 21, 2022
f395e6b
prepare nif for two inputs
Janix4000 Jul 21, 2022
2c28aee
fix compile warnings
Janix4000 Jul 22, 2022
e3c3fb5
add pipeline basics
Janix4000 Jul 22, 2022
7987115
add state to merge_frames
Janix4000 Jul 22, 2022
d490331
add test basics
Janix4000 Jul 22, 2022
f6af097
remove wrong pipeline structure
Janix4000 Jul 22, 2022
431ffc4
pass first test
Janix4000 Jul 22, 2022
7d8a916
add moduledoc false in unused module
Janix4000 Jul 22, 2022
5debcec
Apply requested changes
Janix4000 Jul 25, 2022
b2ae003
Apply requested changes
Janix4000 Jul 25, 2022
5b3c715
rename test modules
Janix4000 Jul 25, 2022
273f4c0
Create code documentation
Janix4000 Jul 25, 2022
0f12df7
fix compilation errors
Janix4000 Jul 25, 2022
35550ba
describe temporary filter description
Janix4000 Jul 25, 2022
4ddfb89
Correct spelling
Janix4000 Jul 26, 2022
5b90826
add bundlex to formatter
Janix4000 Jul 26, 2022
4ff9b18
replace "create" with "init"
Janix4000 Jul 26, 2022
d74885b
replace raw parameters with array of videos
Janix4000 Jul 26, 2022
98ed717
remove warning
Janix4000 Jul 26, 2022
bbdbed9
move test utility to membrane module
Janix4000 Jul 26, 2022
27bf28c
describe better filter string
Janix4000 Jul 26, 2022
43c7b6a
move docstring to source files
Janix4000 Jul 26, 2022
2f617a7
move init_raw_video to raw_video.h
Janix4000 Jul 26, 2022
5c39b52
change indent spaces from 4 to 2
Janix4000 Jul 26, 2022
84a27b3
rename filter functions
Janix4000 Jul 26, 2022
36a712b
replace "return int" with error code description
Janix4000 Jul 26, 2022
5b1fb6b
rename error printing function
Janix4000 Jul 26, 2022
c7b932d
add RawVideo parameters into elixir interface
Janix4000 Jul 26, 2022
df1e301
replace own RawVideo with official one
Janix4000 Jul 26, 2022
0da566d
change aliases order
Janix4000 Jul 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions c_src/ffmpeg_video_compositor/filter.c
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#include "filter.h"
Janix4000 marked this conversation as resolved.
Show resolved Hide resolved
/**
* @brief Append a header of the filter description to the string (buffer).
* Creates two input pads with output pads named [in_1] and [in_2]
* Creates \p n_videos input nodes with output pads named [in_1], [in_2], ..,
* [in_ \p n_videos].
*
* @param filters_str Description destination string (buffer)
* @param filters_size Remaining size of the buffer
* @param width Width of the videos
* @param height Height of the videos
* @param pixel_format Pixel format code of the videos
* @return Number of characters written to the buffer
* @param videos Array of input videos.
* @param n_videos Size of the videos array
* @return int
*/
static int init_filters_string(char *filters_str, int filters_size, int width,
int height, int pixel_format);
static int init_filters_string(char *filters_str, int filters_size,
DominikWolek marked this conversation as resolved.
Show resolved Hide resolved
RawVideo videos[], int n_videos);

/**
* @brief Append a main filter description (transformation graph) to the string
Expand All @@ -38,29 +38,28 @@ static void cs_printAVError(const char *msg, int returnCode) {
fprintf(stderr, "%s: %s\n", msg, av_err2str(returnCode));
}

int init_filter_description(char *filter_str, int filters_size, int width,
int height, int pixel_format) {
int init_filter_description(char *filter_str, int filter_size,
RawVideo videos[], int n_videos) {
int filter_end = 0;
filter_end +=
init_filters_string(filter_str + filter_end, filters_size - filter_end,
width, height, pixel_format);
filter_end += init_filters_string(
filter_str + filter_end, filter_size - filter_end, videos, n_videos);
filter_end += apply_filters_options_string(filter_str + filter_end,
filters_size - filter_end);
filter_size - filter_end);
filter_end += finish_filters_string(filter_str + filter_end,
filters_size - filter_end);
filter_size - filter_end);
return filter_end;
}

static int init_filters_string(char *filters_str, int filters_size, int width,
int height, int pixel_format) {
const int n_videos = 2;
static int init_filters_string(char *filters_str, int filters_size,
RawVideo videos[], int n_videos) {
int filter_end = 0;
for (int i = 0; i < n_videos; ++i) {
filter_end +=
snprintf(filters_str + filter_end, filters_size - filter_end,
"buffer=video_size=%dx%d:pix_fmt=%d:time_base=%d/"
"%d [in_%d];\n",
width, height, pixel_format, 1, 1, i + 1);
RawVideo *video = &videos[i];
filter_end += snprintf(
filters_str + filter_end, filters_size - filter_end,
"buffer=video_size=%dx%d:pix_fmt=%d:time_base=%d/"
"%d [in_%d];\n",
video->width, video->height, video->pixel_format, 1, 1, i + 1);
Janix4000 marked this conversation as resolved.
Show resolved Hide resolved
}
return filter_end;
}
Expand Down
15 changes: 7 additions & 8 deletions c_src/ffmpeg_video_compositor/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,19 @@ typedef struct VState {
* @param filters_descr String description of the filter graph. This should
* follow FFmpeg filter documentation.
* @param filter Pointer to the filter graph.
* @return int Return code. Return 0 on success, a negative value on failure.
* @return Return code. Return 0 on success, a negative value on failure.
*/
Janix4000 marked this conversation as resolved.
Show resolved Hide resolved
int init_filters(const char *filters_descr, FilterState *filter);
Janix4000 marked this conversation as resolved.
Show resolved Hide resolved

/**
* @brief Creates a filter description string in an FFmpeg format and stores it
* in the given string. The function assumes two input videos.
* in the given string.
*
* @param filter_str Description destination (buffer)
* @param filter_size Maximum size of the filter description (buffer size)
* @param width Width of the videos
* @param height Height of the videos
* @param pixel_format Pixel format code of the videos
* @return Number of characters written to the buffer
* @param videos Array of input videos.
* @param n_videos Size of the videos array
* @return int
*/
Janix4000 marked this conversation as resolved.
Show resolved Hide resolved
int init_filter_description(char *filter_str, int filter_size, int width,
int height, int pixel_format);
int init_filter_description(char *filter_str, int filter_size,
Janix4000 marked this conversation as resolved.
Show resolved Hide resolved
RawVideo videos[], int n_videos);
77 changes: 50 additions & 27 deletions c_src/ffmpeg_video_compositor/video_compositor.c
Original file line number Diff line number Diff line change
@@ -1,56 +1,79 @@
#include "video_compositor.h"
Janix4000 marked this conversation as resolved.
Show resolved Hide resolved

/**
* @brief Create a unifex filter object
*
* @param env Unifex environment
* @param filter_description Description of the FFmpeg filter (transformation
* graph), given in a string
* @param videos Array of input videos
* @param n_videos Size of the videos array
* @return UNIFEX_TERM
*/
static UNIFEX_TERM init_unifex_filter(UnifexEnv *env,
const char *filter_description,
int pixel_format, int width, int height);
RawVideo videos[], int n_videos);

int init_raw_video(RawVideo *raw_video, int width, int height,
const char *pixel_format_name) {
int pixel_format = get_pixel_format(pixel_format_name);
if (pixel_format < 0) {
return -1;
}
raw_video->width = width;
raw_video->height = height;
raw_video->pixel_format = pixel_format;
return 0;
}

/**
* @brief Initializes the state of the video compositor, creates a filter graph
* @brief Initializes the state of the video compositor and creates a filter
* graph. The function assumes two input videos and one output video.
*
* @param env Unifex environment
* @param width Width of the videos
* @param height Height of the videos
* @param pixel_format_name Pixel format of the videos, given in a string
* @param first_width Width of the first video
* @param first_height Height of the first video
* @param first_pixel_format_name Pixel format of the first video, given in a
* string
* @param second_width Width of the second video
* @param second_height Height of the second video
* @param second_pixel_format_name Pixel format of the second video, given in a
* string
* @return UNIFEX_TERM
*/
UNIFEX_TERM init(UnifexEnv *env, int width, int height,
char *pixel_format_name) {
UNIFEX_TERM init(UnifexEnv *env, int first_width, int first_height,
char *first_pixel_format_name, int second_width,
int second_height, char *second_pixel_format_name) {
UNIFEX_TERM result;
char filter_str[512];

int pixel_format = get_pixel_format(pixel_format_name);
if (pixel_format < 0) {
RawVideo videos[2];
if (init_raw_video(&videos[0], first_width, first_height,
first_pixel_format_name) < 0) {
result = init_result_error(env, "unsupported_pixel_format");
goto end;
}
if (init_raw_video(&videos[1], second_width, second_height,
second_pixel_format_name) < 0) {
result = init_result_error(env, "unsupported_pixel_format");
goto end;
}
init_filter_description(filter_str, sizeof filter_str, width, height,
pixel_format);
result = init_unifex_filter(env, filter_str, pixel_format, width, height);

init_filter_description(filter_str, sizeof filter_str, videos,
SIZE(videos));
result = init_unifex_filter(env, filter_str, videos, SIZE(videos));
end:
return result;
}

/**
* @brief Create a unifex filter object
*
* @param env Unifex environment
* @param filter_description Description of the FFmpeg filter (transformation
* graph), given in a string
* @param pixel_format Pixel format code of the videos
* @param width Width of the videos
* @param height Height of the videos
* @return UNIFEX_TERM
*/
static UNIFEX_TERM init_unifex_filter(UnifexEnv *env,
const char *filter_description,
int pixel_format, int width, int height) {
RawVideo videos[], int n_videos) {
UNIFEX_TERM result;

State *state = unifex_alloc_state(env);
for (int i = 0; i < SIZE(state->vstate.videos); i++) {
state->vstate.videos[i].height = height;
state->vstate.videos[i].width = width;
state->vstate.videos[i].pixel_format = pixel_format;
state->vstate.videos[i] = videos[i];
}

if (init_filters(filter_description, &state->vstate.filter) < 0) {
Expand Down
9 changes: 6 additions & 3 deletions c_src/ffmpeg_video_compositor/video_compositor.spec.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ module Membrane.VideoCompositor.FFmpeg.Native
state_type "State"

spec init(
width :: int,
height :: int,
pixel_format_name :: atom
first_width :: int,
first_height :: int,
first_pixel_format_name :: atom,
second_width :: int,
second_height :: int,
second_pixel_format_name :: atom
) :: {:ok :: label, state} | {:error :: label, reason :: atom}

spec apply_filter(left_payload :: payload, right_payload :: payload, state) ::
Expand Down
3 changes: 3 additions & 0 deletions test/video_compositor/video_compositor_ffmpeg_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ defmodule VideoCompositor.FFmpeg.NativeTest do

assert {:ok, ref} =
Native.init(
640,
360,
:I420,
640,
360,
:I420
Expand Down