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 #758

Open
gavv opened this issue Jul 13, 2024 · 7 comments
Open

Implement IFrameEncoder / IFrameDecoder using libvorbis #758

gavv opened this issue Jul 13, 2024 · 7 comments
Assignees
Labels
codecs Audio and FEC codecs easy hacks The solution is expected to be straightforward even if you are new to the project enhancement help wanted An important and awaited task but we have no human resources for it yet much-needed This issue is needed most among other help-wanted issues

Comments

@gavv
Copy link
Member

gavv commented Jul 13, 2024

We have two interfaces IFrameEncoder and IFrameDecoder that are used to encode audio samples into packet payload and decode it back. Currently they're implemented using PcmEncoder and PcmDecoder (for uncompressed PCM).

Now we need to add two more implementations: VorbisEncoder and VorbisDecoder, that will use libvorbis library to do the job.

We also need to add new encoder & decoder to the list of tested codecs in test_frame_encoder_decoder.cpp.

@gavv gavv added enhancement help wanted An important and awaited task but we have no human resources for it yet easy hacks The solution is expected to be straightforward even if you are new to the project codecs Audio and FEC codecs labels Jul 13, 2024
@gavv gavv added the much-needed This issue is needed most among other help-wanted issues label Jul 13, 2024
@runei
Copy link

runei commented Jul 27, 2024

Hi, I am interested in solving this issue.

@gavv
Copy link
Member Author

gavv commented Jul 28, 2024

Welcome, thank you!

@gavv
Copy link
Member Author

gavv commented Jul 28, 2024

Let me know if you'll need help/hints with the build system.

Also, if libogg dependency can be disabled, I suppose we should do it, because all we need is vorbis encoder/decoder, we don't need to work with ogg files.

@runei
Copy link

runei commented Jul 30, 2024

Hi @gavv ,

I tried without the libogg, but it fails when installing vorbis. According to the README, "You'll need libogg (distributed separately) to compile this library.", which is why I tried to install it before libvorbis.

I managed to install vorbis with the build script after installing libogg. But I'm having trouble in installing the libogg with the script, since I used "make install" on the terminal.
Using "execute(ctx, 'make install')" on the script need permission on CI, as it creates the files at " /usr/local/lib".
So how can I install libogg within the same folder and utilize the generated files for the libvorbis installation?

@gavv
Copy link
Member Author

gavv commented Aug 1, 2024

Oh, I see. I assumed that libogg should support using libvorbis as codec, but instead, libvorbis supports using libogg for muxing.

For rfc5215, we'll need to disable ogg muxing, which seems to be feasible. libvorbis encodes packets into a struct from libogg (ogg_packet), however this struct does not yet have OGG headers, only opaque codec-specific data. OGG headers are added later when you use libogg API, and we can just don't use it and use data from ogg_packet directly.


When build-3rdparty.py builds a package, it never runs make install. This script is for building dependencies locally, not installing them system wide. Instead, in the end of building every package, there are calls to install_tree() and install_files() functions that install headers and libraries into a local directory specific for this package.

For example, here is what is "installed" for json-c:

tree -L 2 build/3rdparty/x86_64-pc-linux-gnu/clang-14.0.6-release/json-c-0.12-20140410/
build/3rdparty/x86_64-pc-linux-gnu/clang-14.0.6-release/json-c-0.12-20140410/
├── include
│   ├── doc
│   ├── tests
│   ├── arraylist.h
│   ├── bits.h
│   ├── config.h
│   ├── debug.h
│   ├── json_config.h
│   ├── json_c_version.h
│   ├── json.h
│   ├── json_inttypes.h
│   ├── json_object.h
│   ├── json_object_iterator.h
│   ├── json_object_private.h
│   ├── json_tokener.h
│   ├── json_util.h
│   ├── linkhash.h
│   ├── math_compat.h
│   ├── printbuf.h
│   └── random_seed.h
├── lib
│   └── libjson-c.a
├── src
│   ├── json-c-json-c-0.12-20140410
│   └── json-c-0.12-20140410.tar.gz
├── build.log
└── commit

These include and lib directories are added to the include and library search path in scons, so we can use the dependency in our code.


OK, so what we need to do if we need to build libogg and then pass it as a dependency to libvorbis?

Here is an example of similar situation:

if 'pulseaudio' in autobuild_dependencies:
if not 'pulseaudio' in autobuild_explicit_version and not is_crosscompiling:
pa_ver = env.ParseToolVersion('pulseaudio --version')
if pa_ver:
thirdparty_versions['pulseaudio'] = pa_ver
pa_deps = [
'ltdl',
'json-c',
'sndfile',
]
if 'alsa' in autobuild_dependencies:
pa_deps += ['alsa']
env.BuildThirdParty(thirdparty_versions, 'ltdl')
env.BuildThirdParty(thirdparty_versions, 'json-c')
env.BuildThirdParty(thirdparty_versions, 'pulseaudio',
deps=pa_deps, libs=['pulse', 'pulse-simple'])

Here, ltdl and json-c are dependencies of pulseaudio. We first build dependencies, and then pass them via deps argument to BuildThirdParty(). BuildThirdParty, in turn, passes them to build-3rdparty.py script, where those dependencies are stored in ctx.pkg_deps.

When we call format_flags(), it iterates all those dependencies (if they're present) and add their include and lib directories to the flags.

Summary:

  • in 3rdparty/SConscript, if we build libvorbis, we should also build libogg, and pass it to libvorbis using deps arg
  • in build-3rdparty.py, we should support both libogg and libvorbis and properly use install_tree/install_files for both of them
  • in build-3rdparty.py, make sure that you use format_flags() - then it will automatically add libogg dependency to libvorbis

@gavv
Copy link
Member Author

gavv commented Aug 1, 2024

Feel free to ping me if you'll have troubles with those scripts, I know it's not the funniest part :)

@runei
Copy link

runei commented Aug 20, 2024

Hi @gavv , I am working on the handling of Vorbis stream headers. When encoding with vorbis, we should have 3 headers: the identification, comments and codebook headers. And have a few doubts on how to deal with this:

Should we have a dedicated frame for headers or should we split the header across multiple frames together with the data? Or do you have another idea?

My idea would be to create a function uint8_t* create_header_frame(); to handle the header separately, and execute this before the begin_frame

How should we handle cases where the header size exceeds the frame size? Could split the header through multiple frame cause any problems?

Does the encoded_byte_count function need to include the size of the header, or should it only count the encoded data?

I would need to adjust all the unit tests, as well as the packetizer uses the IFrameEncoder. Does this affect any other part of the code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
codecs Audio and FEC codecs easy hacks The solution is expected to be straightforward even if you are new to the project enhancement help wanted An important and awaited task but we have no human resources for it yet much-needed This issue is needed most among other help-wanted issues
Projects
Status: Help wanted
Development

No branches or pull requests

2 participants