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)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(menus)
|
add_subdirectory(menus)
|
||||||
|
add_subdirectory(media)
|
||||||
|
|
||||||
# strip debug symbols into separate file when using gcc.
|
# strip debug symbols into separate file when using gcc.
|
||||||
# to be consistent with Makefile, don't generate for OS X.
|
# 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