Revamp API and start using doxygen
The API used to be designed in such a way to where it would expect exports for each individual source/output/encoder/etc. You would export functions for each and it would automatically load those functions based on a specific naming scheme from the module. The idea behind this was that I wanted to limit the usage of structures in the API so only functions could be used. It was an interesting idea in theory, but this idea turned out to be flawed in a number of ways: 1.) Requiring exports to create sources/outputs/encoders/etc meant that you could not create them by any other means, which meant that things like faruton's .net plugin would become difficult. 2.) Export function declarations could not be checked, therefore if you created a function with the wrong parameters and parameter types, the compiler wouldn't know how to check for that. 3.) Required overly complex load functions in libobs just to handle it. It makes much more sense to just have a load function that you call manually. Complexity is the bane of all good programs. 4.) It required that you have functions of specific names, which looked and felt somewhat unsightly. So, to fix these issues, I replaced it with a more commonly used API scheme, seen commonly in places like kernels and typical C libraries with abstraction. You simply create a structure that contains the callback definitions, and you pass it to a function to register that definition (such as obs_register_source), which you call in the obs_module_load of the module. It will also automatically check the structure size and ensure that it only loads the required values if the structure happened to add new values in an API change. The "main" source file for each module must include obs-module.h, and must use OBS_DECLARE_MODULE() within that source file. Also, started writing some doxygen documentation in to the main library headers. Will add more detailed documentation as I go.
This commit is contained in:
@@ -19,13 +19,9 @@ add_definitions(${Libswresample_DEFINITIONS})
|
||||
set(obs-ffmpeg_SOURCES
|
||||
obs-ffmpeg.c
|
||||
obs-ffmpeg-output.c)
|
||||
|
||||
set(obs-ffmpeg_HEADERS
|
||||
obs-ffmpeg-output.h)
|
||||
|
||||
add_library(obs-ffmpeg MODULE
|
||||
${obs-ffmpeg_SOURCES}
|
||||
${obs-ffmpeg_HEADERS})
|
||||
${obs-ffmpeg_SOURCES})
|
||||
target_link_libraries(obs-ffmpeg
|
||||
libobs
|
||||
${Libavcodec_LIBRARIES}
|
||||
|
@@ -16,7 +16,41 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include <obs.h>
|
||||
#include "obs-ffmpeg-output.h"
|
||||
#include <util/circlebuf.h>
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
struct ffmpeg_data {
|
||||
AVStream *video;
|
||||
AVStream *audio;
|
||||
AVCodec *acodec;
|
||||
AVCodec *vcodec;
|
||||
AVFormatContext *output;
|
||||
struct SwsContext *swscale;
|
||||
|
||||
AVPicture dst_picture;
|
||||
AVFrame *vframe;
|
||||
int frame_size;
|
||||
int total_frames;
|
||||
|
||||
struct circlebuf excess_frames[MAX_AUDIO_PLANES];
|
||||
uint8_t *samples[MAX_AUDIO_PLANES];
|
||||
AVFrame *aframe;
|
||||
int total_samples;
|
||||
|
||||
const char *filename_test;
|
||||
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
struct ffmpeg_output {
|
||||
obs_output_t output;
|
||||
volatile bool active;
|
||||
struct ffmpeg_data ff_data;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* TODO: remove these later */
|
||||
#define SPS_TODO 44100
|
||||
@@ -319,29 +353,29 @@ fail:
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
const char *ffmpeg_output_getname(const char *locale)
|
||||
static const char *ffmpeg_output_getname(const char *locale)
|
||||
{
|
||||
/* TODO: translation */
|
||||
return "FFmpeg file output";
|
||||
}
|
||||
|
||||
void test_callback(void *param, int bla, const char *format, va_list args)
|
||||
static void ffmpeg_log_callback(void *param, int bla, const char *format,
|
||||
va_list args)
|
||||
{
|
||||
blogva(LOG_INFO, format, args);
|
||||
}
|
||||
|
||||
struct ffmpeg_output *ffmpeg_output_create(obs_data_t settings,
|
||||
static struct ffmpeg_output *ffmpeg_output_create(obs_data_t settings,
|
||||
obs_output_t output)
|
||||
{
|
||||
struct ffmpeg_output *data = bzalloc(sizeof(struct ffmpeg_output));
|
||||
data->output = output;
|
||||
|
||||
av_log_set_callback(test_callback);
|
||||
av_log_set_callback(ffmpeg_log_callback);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void ffmpeg_output_destroy(struct ffmpeg_output *data)
|
||||
static void ffmpeg_output_destroy(struct ffmpeg_output *data)
|
||||
{
|
||||
if (data) {
|
||||
if (data->active)
|
||||
@@ -350,7 +384,8 @@ void ffmpeg_output_destroy(struct ffmpeg_output *data)
|
||||
}
|
||||
}
|
||||
|
||||
void ffmpeg_output_update(struct ffmpeg_output *data, obs_data_t settings)
|
||||
static void ffmpeg_output_update(struct ffmpeg_output *data,
|
||||
obs_data_t settings)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -457,7 +492,7 @@ static inline void encode_audio(struct ffmpeg_data *data,
|
||||
|
||||
ret = avcodec_fill_audio_frame(data->aframe, context->channels,
|
||||
context->sample_fmt, data->samples[0],
|
||||
total_size, 1);
|
||||
(int)total_size, 1);
|
||||
if (ret < 0) {
|
||||
blog(LOG_ERROR, "receive_audio: avcodec_fill_audio_frame "
|
||||
"failed: %s", av_err2str(ret));
|
||||
@@ -513,7 +548,7 @@ static void receive_audio(void *param, const struct audio_data *frame)
|
||||
}
|
||||
}
|
||||
|
||||
bool ffmpeg_output_start(struct ffmpeg_output *data)
|
||||
static bool ffmpeg_output_start(struct ffmpeg_output *data)
|
||||
{
|
||||
video_t video = obs_video();
|
||||
audio_t audio = obs_audio();
|
||||
@@ -552,7 +587,7 @@ bool ffmpeg_output_start(struct ffmpeg_output *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffmpeg_output_stop(struct ffmpeg_output *data)
|
||||
static void ffmpeg_output_stop(struct ffmpeg_output *data)
|
||||
{
|
||||
if (data->active) {
|
||||
data->active = false;
|
||||
@@ -562,7 +597,18 @@ void ffmpeg_output_stop(struct ffmpeg_output *data)
|
||||
}
|
||||
}
|
||||
|
||||
bool ffmpeg_output_active(struct ffmpeg_output *data)
|
||||
static bool ffmpeg_output_active(struct ffmpeg_output *data)
|
||||
{
|
||||
return data->active;
|
||||
}
|
||||
|
||||
struct obs_output_info ffmpeg_output = {
|
||||
.id = "ffmpeg_output",
|
||||
.getname = ffmpeg_output_getname,
|
||||
.create = ffmpeg_output_create,
|
||||
.destroy = ffmpeg_output_destroy,
|
||||
.update = ffmpeg_output_update,
|
||||
.start = ffmpeg_output_start,
|
||||
.stop = ffmpeg_output_stop,
|
||||
.active = ffmpeg_output_active
|
||||
};
|
||||
|
@@ -1,69 +0,0 @@
|
||||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <util/c99defs.h>
|
||||
#include <util/circlebuf.h>
|
||||
#include <media-io/audio-io.h>
|
||||
#include <media-io/video-io.h>
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
struct ffmpeg_data {
|
||||
AVStream *video;
|
||||
AVStream *audio;
|
||||
AVCodec *acodec;
|
||||
AVCodec *vcodec;
|
||||
AVFormatContext *output;
|
||||
struct SwsContext *swscale;
|
||||
|
||||
AVPicture dst_picture;
|
||||
AVFrame *vframe;
|
||||
int frame_size;
|
||||
int total_frames;
|
||||
|
||||
struct circlebuf excess_frames[MAX_AUDIO_PLANES];
|
||||
uint8_t *samples[MAX_AUDIO_PLANES];
|
||||
AVFrame *aframe;
|
||||
int total_samples;
|
||||
|
||||
const char *filename_test;
|
||||
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
struct ffmpeg_output {
|
||||
obs_output_t output;
|
||||
volatile bool active;
|
||||
struct ffmpeg_data ff_data;
|
||||
};
|
||||
|
||||
EXPORT const char *ffmpeg_output_getname(const char *locale);
|
||||
|
||||
EXPORT struct ffmpeg_output *ffmpeg_output_create(obs_data_t settings,
|
||||
obs_output_t output);
|
||||
EXPORT void ffmpeg_output_destroy(struct ffmpeg_output *data);
|
||||
|
||||
EXPORT void ffmpeg_output_update(struct ffmpeg_output *data,
|
||||
obs_data_t settings);
|
||||
|
||||
EXPORT bool ffmpeg_output_start(struct ffmpeg_output *data);
|
||||
EXPORT void ffmpeg_output_stop(struct ffmpeg_output *data);
|
||||
|
||||
EXPORT bool ffmpeg_output_active(struct ffmpeg_output *data);
|
@@ -1,21 +1,11 @@
|
||||
#include <string.h>
|
||||
#include <obs.h>
|
||||
#include <obs-module.h>
|
||||
|
||||
EXPORT bool enum_outputs(size_t idx, const char **name);
|
||||
EXPORT uint32_t module_version(uint32_t in_version);
|
||||
OBS_DECLARE_MODULE()
|
||||
|
||||
static const char *outputs[] = {"ffmpeg_output"};
|
||||
extern struct obs_output_info ffmpeg_output;
|
||||
|
||||
uint32_t module_version(uint32_t in_version)
|
||||
bool obs_module_load(uint32_t obs_version)
|
||||
{
|
||||
return LIBOBS_API_VER;
|
||||
}
|
||||
|
||||
bool enum_outputs(size_t idx, const char **name)
|
||||
{
|
||||
if (idx >= sizeof(outputs)/sizeof(const char*))
|
||||
return false;
|
||||
|
||||
*name = outputs[idx];
|
||||
obs_register_output(&ffmpeg_output);
|
||||
return true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user