mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2025-07-03 16:25:31 +00:00
Decode Opus and play using Alsa
This commit is contained in:
parent
5647f7a90d
commit
a1e24afaa8
@ -16,9 +16,11 @@ find_package(Threads)
|
|||||||
find_package(CURL)
|
find_package(CURL)
|
||||||
find_package(OpenSSL)
|
find_package(OpenSSL)
|
||||||
find_package(EXPAT)
|
find_package(EXPAT)
|
||||||
|
find_package(ALSA)
|
||||||
|
find_package(Opus)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(EVDEV libevdev)
|
pkg_check_modules(EVDEV libevdev)
|
||||||
|
|
||||||
include_directories(./moonlight-common-c ${EVDEV_INCLUDE_DIRS})
|
include_directories(./moonlight-common-c ${OPUS_INCLUDE_DIRS} ${EVDEV_INCLUDE_DIRS})
|
||||||
target_link_libraries (moonlight PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${EXPAT_LIBRARIES} ${EVDEV_LIBRARIES})
|
target_link_libraries (moonlight PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${EXPAT_LIBRARIES} ${EVDEV_LIBRARIES} ${ALSA_LIBRARY} ${OPUS_LIBRARY})
|
||||||
|
@ -31,6 +31,7 @@ implementation.
|
|||||||
|
|
||||||
* Download [GeForce Experience](http://www.geforce.com/geforce-experience) and install on your Windows PC
|
* Download [GeForce Experience](http://www.geforce.com/geforce-experience) and install on your Windows PC
|
||||||
* Download the compiled version from the [GitHub releases page](https://github.com/irtimmer/moonlight-embedded/releases)
|
* Download the compiled version from the [GitHub releases page](https://github.com/irtimmer/moonlight-embedded/releases)
|
||||||
|
* Install libopus0 (Debian/Raspbian) or opus (Arch Linux/Fedora/Pidora)
|
||||||
* [Configure sound](http://elinux.org/R-Pi_Troubleshooting#Sound)
|
* [Configure sound](http://elinux.org/R-Pi_Troubleshooting#Sound)
|
||||||
|
|
||||||
##Requirements
|
##Requirements
|
||||||
@ -55,6 +56,7 @@ implementation.
|
|||||||
|
|
||||||
* Install cmake
|
* Install cmake
|
||||||
* Install cryptographics libraries libssl-dev (Debian/Raspbian) or openssl-devel (Fedora/Pidora) or openssl (Arch Linux)
|
* Install cryptographics libraries libssl-dev (Debian/Raspbian) or openssl-devel (Fedora/Pidora) or openssl (Arch Linux)
|
||||||
|
* Install audio libraries libopus-dev and libasound2-dev (Debian/Raspbian) or opus-devel and alsa-lib-devel (Fedora/Pidora) or opus and alsa-lib (Arch Linux)
|
||||||
* Initialize the git submodules ``git submodule update --init``
|
* Initialize the git submodules ``git submodule update --init``
|
||||||
|
|
||||||
```
|
```
|
||||||
|
81
src/audio.c
81
src/audio.c
@ -20,30 +20,91 @@
|
|||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <opus.h>
|
||||||
|
#include <alsa/asoundlib.h>
|
||||||
|
|
||||||
static FILE* fd;
|
#define CHECK_RETURN(f) if ((rc = f) < 0) { printf("Alsa error code %d\n", rc); exit(-1); }
|
||||||
static const char* fileName = "fake.opus";
|
|
||||||
|
|
||||||
void audio_renderer_init() {
|
#define SAMPLE_RATE 48000
|
||||||
|
#define CHANNEL_COUNT 2
|
||||||
|
#define FRAME_SIZE 240
|
||||||
|
|
||||||
|
static const char* device = "default";
|
||||||
|
|
||||||
|
static snd_pcm_t *handle;
|
||||||
|
static OpusDecoder* decoder;
|
||||||
|
static short pcmBuffer[FRAME_SIZE * CHANNEL_COUNT];
|
||||||
|
|
||||||
|
static void audio_renderer_init() {
|
||||||
printf("audio_renderer_init\n");
|
printf("audio_renderer_init\n");
|
||||||
fd = fopen(fileName, "w");
|
int rc;
|
||||||
|
decoder = opus_decoder_create(SAMPLE_RATE, CHANNEL_COUNT, &rc);
|
||||||
|
|
||||||
|
snd_pcm_hw_params_t *hw_params;
|
||||||
|
snd_pcm_sw_params_t *sw_params;
|
||||||
|
snd_pcm_uframes_t period_size = FRAME_SIZE * CHANNEL_COUNT * 2;
|
||||||
|
snd_pcm_uframes_t buffer_size = 12 * period_size;
|
||||||
|
unsigned int sampleRate = SAMPLE_RATE;
|
||||||
|
|
||||||
|
/* Open PCM device for playback. */
|
||||||
|
CHECK_RETURN(snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))
|
||||||
|
|
||||||
|
/* Set hardware parameters */
|
||||||
|
CHECK_RETURN(snd_pcm_hw_params_malloc(&hw_params));
|
||||||
|
CHECK_RETURN(snd_pcm_hw_params_any(handle, hw_params));
|
||||||
|
CHECK_RETURN(snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED));
|
||||||
|
CHECK_RETURN(snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE));
|
||||||
|
CHECK_RETURN(snd_pcm_hw_params_set_rate_near(handle, hw_params, &sampleRate, NULL));
|
||||||
|
CHECK_RETURN(snd_pcm_hw_params_set_channels(handle, hw_params, CHANNEL_COUNT));
|
||||||
|
CHECK_RETURN(snd_pcm_hw_params_set_buffer_size_near(handle, hw_params, &buffer_size));
|
||||||
|
CHECK_RETURN(snd_pcm_hw_params_set_period_size_near(handle, hw_params, &period_size, NULL));
|
||||||
|
CHECK_RETURN(snd_pcm_hw_params(handle, hw_params));
|
||||||
|
snd_pcm_hw_params_free(hw_params);
|
||||||
|
|
||||||
|
/* Set software parameters */
|
||||||
|
CHECK_RETURN(snd_pcm_sw_params_malloc(&sw_params));
|
||||||
|
CHECK_RETURN(snd_pcm_sw_params_current(handle, sw_params));
|
||||||
|
CHECK_RETURN(snd_pcm_sw_params_set_start_threshold(handle, sw_params, buffer_size - period_size));
|
||||||
|
CHECK_RETURN(snd_pcm_sw_params_set_avail_min(handle, sw_params, period_size));
|
||||||
|
CHECK_RETURN(snd_pcm_sw_params(handle, sw_params));
|
||||||
|
snd_pcm_sw_params_free(sw_params);
|
||||||
|
|
||||||
|
CHECK_RETURN(snd_pcm_prepare(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_renderer_start() {
|
static void audio_renderer_start() {
|
||||||
printf("audio_renderer_start\n");
|
printf("audio_renderer_start\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_renderer_stop() {
|
static void audio_renderer_stop() {
|
||||||
printf("audio_renderer_stop\n");
|
printf("audio_renderer_stop\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_renderer_release() {
|
static void audio_renderer_release() {
|
||||||
printf("audio_renderer_release\n");
|
printf("audio_renderer_release\n");
|
||||||
fclose(fd);
|
if (decoder != NULL)
|
||||||
|
opus_decoder_destroy(decoder);
|
||||||
|
|
||||||
|
if (handle != NULL) {
|
||||||
|
snd_pcm_drain(handle);
|
||||||
|
snd_pcm_close(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_renderer_decode_and_play_sample(char* data, int length) {
|
static void audio_renderer_decode_and_play_sample(char* data, int length) {
|
||||||
fwrite(data, length, 1, fd);
|
int decodeLen = opus_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0);
|
||||||
|
if (decodeLen > 0) {
|
||||||
|
int rc = snd_pcm_writei(handle, pcmBuffer, decodeLen);
|
||||||
|
if (rc == -EPIPE)
|
||||||
|
snd_pcm_recover(handle, rc, 1);
|
||||||
|
|
||||||
|
if (rc<0)
|
||||||
|
printf("Alsa error from writei: %d\n", rc);
|
||||||
|
else if (decodeLen != rc)
|
||||||
|
printf("Alsa shortm write, write %d frames\n", rc);
|
||||||
|
} else {
|
||||||
|
printf("Opus error from decode: %d\n", decodeLen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AUDIO_RENDERER_CALLBACKS audio_callbacks = {
|
AUDIO_RENDERER_CALLBACKS audio_callbacks = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user