mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Add basic multimedia container and encoder interfaces
Adds the media subdirectory.
This commit is contained in:
parent
8ee785bb7e
commit
3b5245f974
7 changed files with 272 additions and 0 deletions
|
|
@ -549,6 +549,7 @@ if(SRB2_CONFIG_ENABLE_TESTS)
|
|||
add_subdirectory(tests)
|
||||
endif()
|
||||
add_subdirectory(menus)
|
||||
add_subdirectory(media)
|
||||
|
||||
# strip debug symbols into separate file when using gcc.
|
||||
# to be consistent with Makefile, don't generate for OS X.
|
||||
|
|
|
|||
7
src/media/CMakeLists.txt
Normal file
7
src/media/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
target_sources(SRB2SDL2 PRIVATE
|
||||
audio_encoder.hpp
|
||||
container.hpp
|
||||
encoder.hpp
|
||||
video_encoder.hpp
|
||||
video_frame.hpp
|
||||
)
|
||||
39
src/media/audio_encoder.hpp
Normal file
39
src/media/audio_encoder.hpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_MEDIA_AUDIO_ENCODER_HPP__
|
||||
#define __SRB2_MEDIA_AUDIO_ENCODER_HPP__
|
||||
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
#include "encoder.hpp"
|
||||
|
||||
namespace srb2::media
|
||||
{
|
||||
|
||||
class AudioEncoder : virtual public MediaEncoder
|
||||
{
|
||||
public:
|
||||
using sample_buffer_t = tcb::span<const float>;
|
||||
|
||||
struct Config
|
||||
{
|
||||
int channels;
|
||||
int sample_rate;
|
||||
};
|
||||
|
||||
virtual void encode(sample_buffer_t samples) = 0;
|
||||
|
||||
virtual int channels() const = 0;
|
||||
virtual int sample_rate() const = 0;
|
||||
};
|
||||
|
||||
}; // namespace srb2::media
|
||||
|
||||
#endif // __SRB2_MEDIA_AUDIO_ENCODER_HPP__
|
||||
53
src/media/container.hpp
Normal file
53
src/media/container.hpp
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
// RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_MEDIA_CONTAINER_HPP__
|
||||
#define __SRB2_MEDIA_CONTAINER_HPP__
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "audio_encoder.hpp"
|
||||
#include "video_encoder.hpp"
|
||||
|
||||
namespace srb2::media
|
||||
{
|
||||
|
||||
class MediaContainer
|
||||
{
|
||||
public:
|
||||
using dtor_cb_t = std::function<void(const MediaContainer&)>;
|
||||
using time_unit_t = std::chrono::duration<float>;
|
||||
|
||||
struct Config
|
||||
{
|
||||
std::string file_name;
|
||||
dtor_cb_t destructor_callback;
|
||||
};
|
||||
|
||||
virtual ~MediaContainer() = default;
|
||||
|
||||
virtual std::unique_ptr<AudioEncoder> make_audio_encoder(AudioEncoder::Config config) = 0;
|
||||
virtual std::unique_ptr<VideoEncoder> make_video_encoder(VideoEncoder::Config config) = 0;
|
||||
|
||||
virtual const char* name() const = 0;
|
||||
virtual const char* file_name() const = 0;
|
||||
|
||||
// These are normally estimates. However, when called from
|
||||
// Config::destructor_callback, these are the exact final
|
||||
// values.
|
||||
virtual time_unit_t duration() const = 0;
|
||||
virtual std::size_t size() const = 0;
|
||||
};
|
||||
|
||||
}; // namespace srb2::media
|
||||
|
||||
#endif // __SRB2_MEDIA_CONTAINER_HPP__
|
||||
51
src/media/encoder.hpp
Normal file
51
src/media/encoder.hpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_MEDIA_ENCODER_HPP__
|
||||
#define __SRB2_MEDIA_ENCODER_HPP__
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
namespace srb2::media
|
||||
{
|
||||
|
||||
class MediaEncoder
|
||||
{
|
||||
public:
|
||||
using time_unit_t = std::chrono::duration<float>;
|
||||
|
||||
struct BitRate
|
||||
{
|
||||
std::size_t bits; // 8 bits = 1 byte :)
|
||||
time_unit_t period;
|
||||
};
|
||||
|
||||
virtual ~MediaEncoder() = default;
|
||||
|
||||
// Should be called finally but it's optional.
|
||||
virtual void flush() = 0;
|
||||
|
||||
virtual const char* name() const = 0;
|
||||
|
||||
// Returns an average bit rate over a constant period of
|
||||
// time, assuming no frames drops.
|
||||
virtual BitRate estimated_bit_rate() const = 0;
|
||||
|
||||
protected:
|
||||
using frame_buffer_t = tcb::span<const std::byte>;
|
||||
|
||||
virtual void write_frame(frame_buffer_t frame, time_unit_t timestamp, bool is_key_frame) = 0;
|
||||
};
|
||||
|
||||
}; // namespace srb2::media
|
||||
|
||||
#endif // __SRB2_MEDIA_ENCODER_HPP__
|
||||
58
src/media/video_encoder.hpp
Normal file
58
src/media/video_encoder.hpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_MEDIA_VIDEO_ENCODER_HPP__
|
||||
#define __SRB2_MEDIA_VIDEO_ENCODER_HPP__
|
||||
|
||||
#include "encoder.hpp"
|
||||
#include "video_frame.hpp"
|
||||
|
||||
namespace srb2::media
|
||||
{
|
||||
|
||||
class VideoEncoder : virtual public MediaEncoder
|
||||
{
|
||||
public:
|
||||
struct Config
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int frame_rate;
|
||||
VideoFrame::BufferMethod buffer_method;
|
||||
};
|
||||
|
||||
struct FrameCount
|
||||
{
|
||||
// Number of real frames, not counting frame skips.
|
||||
int frames;
|
||||
|
||||
time_unit_t duration;
|
||||
};
|
||||
|
||||
// VideoFrame::width() and VideoFrame::height() should be
|
||||
// used on the returned frame.
|
||||
virtual VideoFrame::instance_t new_frame(int width, int height, int pts) = 0;
|
||||
|
||||
virtual void encode(VideoFrame::instance_t frame) = 0;
|
||||
|
||||
virtual int width() const = 0;
|
||||
virtual int height() const = 0;
|
||||
virtual int frame_rate() const = 0;
|
||||
|
||||
// Reports the number of threads used, if the encoder is
|
||||
// multithreaded.
|
||||
virtual int thread_count() const = 0;
|
||||
|
||||
// Number of frames fully encoded so far.
|
||||
virtual FrameCount frame_count() const = 0;
|
||||
};
|
||||
|
||||
}; // namespace srb2::media
|
||||
|
||||
#endif // __SRB2_MEDIA_VIDEO_ENCODER_HPP__
|
||||
63
src/media/video_frame.hpp
Normal file
63
src/media/video_frame.hpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James Robert Roman
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __SRB2_MEDIA_VIDEO_FRAME_HPP__
|
||||
#define __SRB2_MEDIA_VIDEO_FRAME_HPP__
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include <tcb/span.hpp>
|
||||
|
||||
namespace srb2::media
|
||||
{
|
||||
|
||||
class VideoFrame
|
||||
{
|
||||
public:
|
||||
using instance_t = std::unique_ptr<VideoFrame>;
|
||||
|
||||
enum class BufferMethod
|
||||
{
|
||||
// Returns an already allocated buffer for each
|
||||
// frame. See VideoFrame::rgba_buffer(). The encoder
|
||||
// completely manages allocating this buffer.
|
||||
kEncoderAllocatedRGBA8888,
|
||||
};
|
||||
|
||||
struct Buffer
|
||||
{
|
||||
tcb::span<uint8_t> plane;
|
||||
std::size_t row_stride; // size of each row
|
||||
};
|
||||
|
||||
virtual int width() const = 0;
|
||||
virtual int height() const = 0;
|
||||
|
||||
int pts() const { return pts_; }
|
||||
|
||||
// Returns a buffer that should be
|
||||
// filled with RGBA pixels.
|
||||
//
|
||||
// This method may only be used if
|
||||
// the encoder was configured with
|
||||
// BufferMethod::kEncoderAllocatedRGBA8888.
|
||||
virtual const Buffer& rgba_buffer() const = 0;
|
||||
|
||||
protected:
|
||||
VideoFrame(int pts) : pts_(pts) {}
|
||||
|
||||
private:
|
||||
int pts_;
|
||||
};
|
||||
|
||||
}; // namespace srb2::media
|
||||
|
||||
#endif // __SRB2_MEDIA_VIDEO_FRAME_HPP__
|
||||
Loading…
Add table
Reference in a new issue