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

Implement IFrameEncoder / IFrameDecoder using libvorbis #768

Draft
wants to merge 26 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 30 additions & 0 deletions 3rdparty/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ thirdparty_versions = {
'alsa': '1.1.9',
'json-c': '0.12-20140410',
'libatomic_ops': '7.6.10',
'libogg': '1.3.4',
'libunwind': '1.2.1',
'libuv': '1.35.0',
'libvorbis': '1.3.7',
'ltdl': '2.4.6',
'openfec': '1.4.2.11',
'openssl': '3.0.8',
Expand Down Expand Up @@ -48,6 +50,9 @@ external_dependencies.add('ragel')
if 'pulseaudio' in external_dependencies:
external_dependencies.add('sndfile')

if 'libvorbis' in external_dependencies:
external_dependencies.add('libogg')

# on Linux, PulseAudio needs ALSA
if meta.platform in ['linux'] and 'pulseaudio' in external_dependencies:
external_dependencies.add('alsa')
Expand Down Expand Up @@ -254,6 +259,31 @@ elif 'sndfile' in system_dependencies:

env = conf.Finish()

# dep: libogg
if 'libogg' in autobuild_dependencies:
env.BuildThirdParty(thirdparty_versions, 'libogg')

# dep: libvorbis
if 'libvorbis' in autobuild_dependencies:
pa_deps = [
'libogg',
]

env.BuildThirdParty(thirdparty_versions, 'libogg')
env.BuildThirdParty(thirdparty_versions, 'libvorbis',
deps=pa_deps)

elif 'libvorbis' in system_dependencies:
conf = Configure(env, custom_tests=env.CustomTests)

if not conf.AddPkgConfigDependency('vorbis', '--cflags --libs', exclude_from_pc=True):
conf.env.AddManualDependency(libs=['vorbis', 'vorbisenc', 'vorbisfile'], exclude_from_pc=True)

if not conf.CheckLibWithHeaderExt('vorbis', 'vorbis/vorbisenc.h', 'C', run=False):
env.Die("libvorbis not found (see 'config.log' for details)")

env = conf.Finish()

# dep: alsa
if 'alsa' in autobuild_dependencies:
env.BuildThirdParty(thirdparty_versions, 'alsa')
Expand Down
9 changes: 9 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,11 @@ AddOption('--disable-sox',
action='store_true',
help='disable SoX support in tools')

AddOption('--disable-libvorbis',
dest='disable_libvorbis',
action='store_true',
help='disable libvorbis support in tools')

AddOption('--disable-sndfile',
dest='disable_sndfile',
action='store_true',
Expand Down Expand Up @@ -855,6 +860,10 @@ else:
env.Append(ROC_TARGETS=[
'target_pulseaudio',
])
if not GetOption('disable_libvorbis'):
env.Append(ROC_TARGETS=[
'target_libvorbis',
])

if 'target_gnu' not in env['ROC_TARGETS']:
env.Append(ROC_TARGETS=[
Expand Down
2 changes: 1 addition & 1 deletion scripts/ci_checks/linux-x86_64/opensuse.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ scons -Q \
--enable-tests \
--enable-benchmarks \
--enable-examples \
--build-3rdparty=openfec,cpputest \
--build-3rdparty=openfec,cpputest,libvorbis \
test
43 changes: 43 additions & 0 deletions scripts/scons_helpers/build-3rdparty.py
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,49 @@ def die(text, *args):
install_files(ctx, 'builddir/src/pulse/libpulse-simple.so.0', ctx.pkg_rpath_dir)
install_files(ctx, 'builddir/src/libpulsecommon-*.so', ctx.pkg_lib_dir)
install_files(ctx, 'builddir/src/libpulsecommon-*.so', ctx.pkg_rpath_dir)
elif ctx.pkg_name == 'libogg':
download(
ctx,
'https://downloads.xiph.org/releases/ogg/libogg-{ctx.pkg_ver}.tar.gz',
'libogg-{ctx.pkg_ver}.tar.gz')
unpack(ctx,
'libogg-{ctx.pkg_ver}.tar.gz',
'libogg-{ctx.pkg_ver}')
changedir(ctx, 'src/libogg-{ctx.pkg_ver}')
execute(ctx, './configure --host={host} {vars} {flags} {opts}'.format(
host=ctx.toolchain,
vars=format_vars(ctx),
flags=format_flags(ctx, cflags='-fPIC'),
opts=' '.join([
'--disable-shared',
'--enable-static',
])))
execute_make(ctx)
install_tree(ctx, 'include', ctx.pkg_inc_dir, include=['*.h'])
install_files(ctx, 'src/.libs/libogg.a', ctx.pkg_lib_dir)
install_files(ctx, 'ogg.pc', ctx.pkg_lib_dir)
elif ctx.pkg_name == 'libvorbis':
download(
ctx,
'https://downloads.xiph.org/releases/vorbis/libvorbis-{ctx.pkg_ver}.tar.gz',
'libvorbis-{ctx.pkg_ver}.tar.gz')
unpack(ctx,
'libvorbis-{ctx.pkg_ver}.tar.gz',
'libvorbis-{ctx.pkg_ver}')
changedir(ctx, 'src/libvorbis-{ctx.pkg_ver}')
execute(ctx, './configure --host={host} {vars} {flags} {opts}'.format(
host=ctx.toolchain,
vars=format_vars(ctx),
flags=format_flags(ctx, cflags='-fPIC'),
opts=' '.join([
'--disable-shared',
'--enable-static',
])))
execute_make(ctx)
install_tree(ctx, 'include', ctx.pkg_inc_dir, include=['*.h'])
install_files(ctx, 'lib/.libs/libvorbis.a', ctx.pkg_lib_dir)
install_files(ctx, 'lib/.libs/libvorbisenc.a', ctx.pkg_lib_dir)
install_files(ctx, 'lib/.libs/libvorbisfile.a', ctx.pkg_lib_dir)
elif ctx.pkg_name == 'ltdl':
download(
ctx,
Expand Down
21 changes: 21 additions & 0 deletions src/internal_modules/roc_audio/iframe_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,27 @@ class IFrameDecoder : public core::ArenaAllocation {
//! Check if the object was successfully constructed.
virtual status::StatusCode init_status() const = 0;

//! Initialize the decoder with codec-specific headers.
//!
//! @b Parameters
//! - @p headers - pointer to the buffer containing codec-specific header data.
//! - @p headers_size - size of the header buffer in bytes.
//!
//! @remarks
//! This function sets up the decoder using the provided headers, which contain
//! essential configuration information for decoding the audio stream. The headers
//! must be in the format required by the specific codec. This function must be
//! called before decoding any frames.
//!
//! @returns
//! - true if the headers are successfully processed and the decoder is initialized.
//! - false if there is an error in processing the headers.
//!
//! @pre
//! Must be called before begin_frame(), read_samples(), drop_samples(), or
//! end_frame().
virtual bool initialize_headers(const uint8_t* headers, size_t headers_size) = 0;

//! Get decoded stream position.
//!
//! @returns
Expand Down
12 changes: 12 additions & 0 deletions src/internal_modules/roc_audio/iframe_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ class IFrameEncoder : public core::ArenaAllocation {
//! Get encoded frame size in bytes for given number of samples (per channel).
virtual size_t encoded_byte_count(size_t n_samples) const = 0;

//! Get ponter of headers.
//!
//! @returns
//! A pointer to the headers. May return NULL if not applicable.
virtual const uint8_t* get_headers_frame() const = 0;

//! Get the size of the headers.
//!
//! @returns
//! Size of the headers in bytes.
virtual size_t get_headers_frame_size() const = 0;

//! Start encoding a new frame.
//!
//! @remarks
Expand Down
4 changes: 4 additions & 0 deletions src/internal_modules/roc_audio/pcm_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ status::StatusCode PcmDecoder::init_status() const {
return status::StatusOK;
}

bool PcmDecoder::initialize_headers(const uint8_t* headers, size_t headers_size) {
return true;
}

packet::stream_timestamp_t PcmDecoder::position() const {
return stream_pos_;
}
Expand Down
3 changes: 3 additions & 0 deletions src/internal_modules/roc_audio/pcm_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class PcmDecoder : public IFrameDecoder, public core::NonCopyable<> {
//! Check if the object was successfully constructed.
virtual status::StatusCode init_status() const;

//! Get the header information before start decoding
virtual bool initialize_headers(const uint8_t* headers, size_t headers_size);

//! Get current stream position.
virtual packet::stream_timestamp_t position() const;

Expand Down
8 changes: 8 additions & 0 deletions src/internal_modules/roc_audio/pcm_encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ size_t PcmEncoder::encoded_byte_count(size_t num_samples) const {
return pcm_mapper_.output_byte_count(num_samples * n_chans_);
}

const uint8_t* PcmEncoder::get_headers_frame() const {
return NULL;
}

size_t PcmEncoder::get_headers_frame_size() const {
return 0;
}

void PcmEncoder::begin_frame(void* frame_data, size_t frame_size) {
roc_panic_if_not(frame_data);

Expand Down
6 changes: 6 additions & 0 deletions src/internal_modules/roc_audio/pcm_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ class PcmEncoder : public IFrameEncoder, public core::NonCopyable<> {
//! Get encoded frame size in bytes for given number of samples per channel.
virtual size_t encoded_byte_count(size_t num_samples) const;

//! Get headers frame.
const uint8_t* get_headers_frame() const;

//! Get the size of the headers.
size_t get_headers_frame_size() const;

//! Start encoding a new frame.
virtual void begin_frame(void* frame, size_t frame_size);

Expand Down
Loading
Loading