mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
Add workaround for alsa not playing hdmi sound.
Without open/close pcm, hdmi is quiet after second snd_pcm_set_params.
This commit is contained in:
parent
878813f206
commit
92ffd978b0
282
audio.c
282
audio.c
@ -43,6 +43,8 @@
|
|||||||
#endif
|
#endif
|
||||||
//#define USE_ALSA ///< enable alsa support
|
//#define USE_ALSA ///< enable alsa support
|
||||||
//#define USE_OSS ///< enable oss support
|
//#define USE_OSS ///< enable oss support
|
||||||
|
#define noSEARCH_HDMI_BUG
|
||||||
|
#define noSEARCH_HDMI_BUG2
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -88,6 +90,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <alsa/iatomic.h> // portable atomic_t
|
||||||
|
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
@ -110,6 +114,95 @@ static int64_t AudioPTS; ///< audio pts clock
|
|||||||
static pthread_cond_t AudioStartCond; ///< condition variable
|
static pthread_cond_t AudioStartCond; ///< condition variable
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SEARCH_HDMI_BUG2
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// ring buffer
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// FIXME: use this code, to combine alsa&oss ring buffers
|
||||||
|
|
||||||
|
#define AUDIO_RING_MAX 8 ///< number of audio ring buffers
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Audio ring buffer.
|
||||||
|
*/
|
||||||
|
typedef struct _audio_ring_ring_
|
||||||
|
{
|
||||||
|
char FlushBuffers; ///< flag: flush buffers
|
||||||
|
unsigned SampleRate; ///< sample rate in hz
|
||||||
|
unsigned Channels; ///< number of channels
|
||||||
|
} AudioRingRing;
|
||||||
|
|
||||||
|
/// ring of audio ring buffers
|
||||||
|
static AudioRingRing AudioRing[AUDIO_RING_MAX];
|
||||||
|
static int AudioRingWrite; ///< audio ring write pointer
|
||||||
|
static int AudioRingRead; ///< audio ring read pointer
|
||||||
|
static atomic_t AudioRingFilled; ///< how many of the ring is used
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Add sample rate, number of channel change to ring.
|
||||||
|
**
|
||||||
|
** @param freq sample frequency
|
||||||
|
** @param channels number of channels
|
||||||
|
*/
|
||||||
|
static int AudioRingAdd(int freq, int channels)
|
||||||
|
{
|
||||||
|
int filled;
|
||||||
|
|
||||||
|
filled = atomic_read(&AudioRingFilled);
|
||||||
|
if (filled == AUDIO_RING_MAX) { // no free slot
|
||||||
|
// FIXME: can wait for ring buffer empty
|
||||||
|
Error(_("audio: out of ring buffers\n"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
AudioRing[AudioRingWrite].FlushBuffers = 1;
|
||||||
|
AudioRing[AudioRingWrite].SampleRate = freq;
|
||||||
|
AudioRing[AudioRingWrite].Channels = channels;
|
||||||
|
|
||||||
|
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
|
||||||
|
atomic_inc(&AudioRingFilled);
|
||||||
|
|
||||||
|
#ifdef USE_AUDIO_THREAD
|
||||||
|
// tell thread, that something todo
|
||||||
|
AudioRunning = 1;
|
||||||
|
pthread_cond_signal(&AudioStartCond);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Setup audio ring.
|
||||||
|
*/
|
||||||
|
static void AudioRingInit(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AUDIO_RING_MAX; ++i) {
|
||||||
|
// FIXME:
|
||||||
|
//AlsaRingBuffer = RingBufferNew(48000 * 8 * 2); // ~1s 8ch 16bit
|
||||||
|
}
|
||||||
|
// one slot always reservered
|
||||||
|
AudioRingWrite = 1;
|
||||||
|
atomic_set(&AudioRingFilled, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Cleanup audio ring.
|
||||||
|
*/
|
||||||
|
static void AudioRingExit(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < AUDIO_RING_MAX; ++i) {
|
||||||
|
// FIXME:
|
||||||
|
//RingBufferDel(AlsaRingBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_ALSA
|
#ifdef USE_ALSA
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
@ -152,6 +245,7 @@ static int AlsaAddToRingbuffer(const void *samples, int count)
|
|||||||
if (n != count) {
|
if (n != count) {
|
||||||
Error(_("audio/alsa: can't place %d samples in ring buffer\n"), count);
|
Error(_("audio/alsa: can't place %d samples in ring buffer\n"), count);
|
||||||
// too many bytes are lost
|
// too many bytes are lost
|
||||||
|
// FIXME: should skip more, longer skip, but less often?
|
||||||
}
|
}
|
||||||
// Update audio clock
|
// Update audio clock
|
||||||
AudioPTS +=
|
AudioPTS +=
|
||||||
@ -207,7 +301,19 @@ static int AlsaPlayRingbuffer(void)
|
|||||||
snd_pcm_state_name(snd_pcm_state(AlsaPCMHandle)));
|
snd_pcm_state_name(snd_pcm_state(AlsaPCMHandle)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef SEARCH_HDMI_BUG
|
||||||
|
{
|
||||||
|
uint16_t buf[8192];
|
||||||
|
unsigned u;
|
||||||
|
|
||||||
|
for (u = 0; u < sizeof(buf) / 2; u++) {
|
||||||
|
buf[u] = random() & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = sizeof(buf);
|
||||||
|
p = buf;
|
||||||
|
}
|
||||||
|
#else
|
||||||
n = RingBufferGetReadPointer(AlsaRingBuffer, &p);
|
n = RingBufferGetReadPointer(AlsaRingBuffer, &p);
|
||||||
if (!n) { // ring buffer empty
|
if (!n) { // ring buffer empty
|
||||||
if (first) { // only error on first loop
|
if (first) { // only error on first loop
|
||||||
@ -215,6 +321,7 @@ static int AlsaPlayRingbuffer(void)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (n < avail) { // not enough bytes in ring buffer
|
if (n < avail) { // not enough bytes in ring buffer
|
||||||
avail = n;
|
avail = n;
|
||||||
}
|
}
|
||||||
@ -229,7 +336,7 @@ static int AlsaPlayRingbuffer(void)
|
|||||||
} else {
|
} else {
|
||||||
err = snd_pcm_writei(AlsaPCMHandle, p, frames);
|
err = snd_pcm_writei(AlsaPCMHandle, p, frames);
|
||||||
}
|
}
|
||||||
Debug(4, "audio/alsa: wrote %d/%d frames\n", err, frames);
|
//Debug(3, "audio/alsa: wrote %d/%d frames\n", err, frames);
|
||||||
if (err != frames) {
|
if (err != frames) {
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
if (err == -EAGAIN) {
|
if (err == -EAGAIN) {
|
||||||
@ -255,6 +362,19 @@ static int AlsaPlayRingbuffer(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Flush alsa buffers.
|
||||||
|
*/
|
||||||
|
static void AlsaFlushBuffers(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
RingBufferReadAdvance(AlsaRingBuffer, RingBufferUsedBytes(AlsaRingBuffer));
|
||||||
|
if ((err = snd_pcm_drop(AlsaPCMHandle))) {
|
||||||
|
Error(_("audio: snd_pcm_drop(): %s\n"), snd_strerror(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -462,16 +582,10 @@ static void AlsaThread(void)
|
|||||||
if (AlsaFlushBuffer) {
|
if (AlsaFlushBuffer) {
|
||||||
// we can flush too many, but wo cares
|
// we can flush too many, but wo cares
|
||||||
Debug(3, "audio/alsa: flushing buffers\n");
|
Debug(3, "audio/alsa: flushing buffers\n");
|
||||||
RingBufferReadAdvance(AlsaRingBuffer,
|
AlsaFlushBuffers();
|
||||||
RingBufferUsedBytes(AlsaRingBuffer));
|
|
||||||
#if 1
|
|
||||||
if ((err = snd_pcm_drop(AlsaPCMHandle))) {
|
|
||||||
Error(_("audio: snd_pcm_drop(): %s\n"), snd_strerror(err));
|
|
||||||
}
|
|
||||||
if ((err = snd_pcm_prepare(AlsaPCMHandle))) {
|
if ((err = snd_pcm_prepare(AlsaPCMHandle))) {
|
||||||
Error(_("audio: snd_pcm_prepare(): %s\n"), snd_strerror(err));
|
Error(_("audio: snd_pcm_prepare(): %s\n"), snd_strerror(err));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
AlsaFlushBuffer = 0;
|
AlsaFlushBuffer = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -499,8 +613,9 @@ static void AlsaThread(void)
|
|||||||
*/
|
*/
|
||||||
static void AlsaEnqueue(const void *samples, int count)
|
static void AlsaEnqueue(const void *samples, int count)
|
||||||
{
|
{
|
||||||
if (!AlsaRingBuffer || !AlsaPCMHandle) {
|
if (!AlsaRingBuffer || !AlsaPCMHandle || !AudioSampleRate) {
|
||||||
Debug(3, "audio/alsa: not ready\n");
|
printf("%p %p %d\n", AlsaRingBuffer, AlsaPCMHandle, AudioSampleRate);
|
||||||
|
Debug(3, "audio/alsa: enqueue not ready\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (AlsaAddToRingbuffer(samples, count)) {
|
if (AlsaAddToRingbuffer(samples, count)) {
|
||||||
@ -518,35 +633,48 @@ static void AlsaEnqueue(const void *samples, int count)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Initialize alsa pcm device.
|
** Open alsa pcm device.
|
||||||
**
|
|
||||||
** @see AudioPCMDevice
|
|
||||||
*/
|
*/
|
||||||
static void AlsaInitPCM(void)
|
static snd_pcm_t *AlsaOpenPCM(void)
|
||||||
{
|
{
|
||||||
const char *device;
|
const char *device;
|
||||||
snd_pcm_t *handle;
|
snd_pcm_t *handle;
|
||||||
snd_pcm_hw_params_t *hw_params;
|
|
||||||
int err;
|
int err;
|
||||||
snd_pcm_uframes_t buffer_size;
|
|
||||||
|
|
||||||
if (!(device = AudioPCMDevice)) {
|
if (!(device = AudioPCMDevice)) {
|
||||||
if (!(device = getenv("ALSA_DEVICE"))) {
|
if (!(device = getenv("ALSA_DEVICE"))) {
|
||||||
device = "default";
|
device = "default";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME: must set alsa error output to /dev/null
|
|
||||||
if ((err =
|
if ((err =
|
||||||
snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK,
|
snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK,
|
||||||
SND_PCM_NONBLOCK)) < 0) {
|
SND_PCM_NONBLOCK)) < 0) {
|
||||||
Fatal(_("audio/alsa: playback open '%s' error: %s\n"), device,
|
Error(_("audio/alsa: playback open '%s' error: %s\n"), device,
|
||||||
snd_strerror(err));
|
snd_strerror(err));
|
||||||
// FIXME: no fatal error for plugins!
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = snd_pcm_nonblock(handle, 0)) < 0) {
|
if ((err = snd_pcm_nonblock(handle, 0)) < 0) {
|
||||||
Error(_("audio/alsa: can't set block mode: %s\n"), snd_strerror(err));
|
Error(_("audio/alsa: can't set block mode: %s\n"), snd_strerror(err));
|
||||||
}
|
}
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Initialize alsa pcm device.
|
||||||
|
**
|
||||||
|
** @see AudioPCMDevice
|
||||||
|
*/
|
||||||
|
static void AlsaInitPCM(void)
|
||||||
|
{
|
||||||
|
snd_pcm_t *handle;
|
||||||
|
snd_pcm_hw_params_t *hw_params;
|
||||||
|
int err;
|
||||||
|
snd_pcm_uframes_t buffer_size;
|
||||||
|
|
||||||
|
if (!(handle = AlsaOpenPCM())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
snd_pcm_hw_params_alloca(&hw_params);
|
snd_pcm_hw_params_alloca(&hw_params);
|
||||||
// choose all parameters
|
// choose all parameters
|
||||||
@ -556,8 +684,7 @@ static void AlsaInitPCM(void)
|
|||||||
snd_strerror(err));
|
snd_strerror(err));
|
||||||
}
|
}
|
||||||
AlsaCanPause = snd_pcm_hw_params_can_pause(hw_params);
|
AlsaCanPause = snd_pcm_hw_params_can_pause(hw_params);
|
||||||
Info(_("audio/alsa: hw '%s' supports pause: %s\n"), device,
|
Info(_("audio/alsa: supports pause: %s\n"), AlsaCanPause ? "yes" : "no");
|
||||||
AlsaCanPause ? "yes" : "no");
|
|
||||||
snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size);
|
snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size);
|
||||||
Info(_("audio/alsa: max buffer size %lu\n"), buffer_size);
|
Info(_("audio/alsa: max buffer size %lu\n"), buffer_size);
|
||||||
|
|
||||||
@ -656,7 +783,7 @@ static uint64_t AlsaGetDelay(void)
|
|||||||
snd_pcm_sframes_t delay;
|
snd_pcm_sframes_t delay;
|
||||||
uint64_t pts;
|
uint64_t pts;
|
||||||
|
|
||||||
if (!AlsaPCMHandle) {
|
if (!AlsaPCMHandle || !AudioSampleRate) {
|
||||||
return 0UL;
|
return 0UL;
|
||||||
}
|
}
|
||||||
// FIXME: thread safe? __assert_fail_base in snd_pcm_delay
|
// FIXME: thread safe? __assert_fail_base in snd_pcm_delay
|
||||||
@ -702,12 +829,14 @@ static int AlsaSetup(int *freq, int *channels)
|
|||||||
snd_pcm_uframes_t period_size;
|
snd_pcm_uframes_t period_size;
|
||||||
int err;
|
int err;
|
||||||
int ret;
|
int ret;
|
||||||
|
snd_pcm_t *handle;
|
||||||
|
|
||||||
if (!AlsaPCMHandle) { // alsa not running yet
|
if (!AlsaPCMHandle) { // alsa not running yet
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#if 1
|
#if 1
|
||||||
// flush any buffered data
|
// flush any buffered data
|
||||||
|
#ifndef SEARCH_HDMI_BUG2
|
||||||
#ifdef USE_AUDIO_THREAD
|
#ifdef USE_AUDIO_THREAD
|
||||||
if (AudioRunning) {
|
if (AudioRunning) {
|
||||||
while (AudioRunning) {
|
while (AudioRunning) {
|
||||||
@ -718,11 +847,21 @@ static int AlsaSetup(int *freq, int *channels)
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
RingBufferReadAdvance(AlsaRingBuffer,
|
AlsaFlushBuffers();
|
||||||
RingBufferUsedBytes(AlsaRingBuffer));
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
AudioPTS = INT64_C(0x8000000000000000);
|
AudioPTS = INT64_C(0x8000000000000000);
|
||||||
|
|
||||||
|
if (1) { // close+open to fix hdmi no sound bugs
|
||||||
|
handle = AlsaPCMHandle;
|
||||||
|
AlsaPCMHandle = NULL;
|
||||||
|
snd_pcm_close(handle);
|
||||||
|
if (!(handle = AlsaOpenPCM())) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
AlsaPCMHandle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
try_again:
|
try_again:
|
||||||
AudioChannels = *channels;
|
AudioChannels = *channels;
|
||||||
@ -844,6 +983,41 @@ static int AlsaSetup(int *freq, int *channels)
|
|||||||
// FIXME: use hw_params for buffer_size period_size
|
// FIXME: use hw_params for buffer_size period_size
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if (0) { // no underruns allowed, play silence
|
||||||
|
snd_pcm_sw_params_t *sw_params;
|
||||||
|
snd_pcm_uframes_t boundary;
|
||||||
|
|
||||||
|
snd_pcm_sw_params_alloca(&sw_params);
|
||||||
|
err = snd_pcm_sw_params_current(AlsaPCMHandle, sw_params);
|
||||||
|
if (err < 0) {
|
||||||
|
Error(_("audio: snd_pcm_sw_params_current failed: %s\n"),
|
||||||
|
snd_strerror(err));
|
||||||
|
}
|
||||||
|
if ((err = snd_pcm_sw_params_get_boundary(sw_params, &boundary)) < 0) {
|
||||||
|
Error(_("audio: snd_pcm_sw_params_get_boundary failed: %s\n"),
|
||||||
|
snd_strerror(err));
|
||||||
|
}
|
||||||
|
Debug(4, "audio/alsa: boundary %lu frames\n", boundary);
|
||||||
|
if ((err =
|
||||||
|
snd_pcm_sw_params_set_stop_threshold(AlsaPCMHandle, sw_params,
|
||||||
|
boundary)) < 0) {
|
||||||
|
Error(_("audio: snd_pcm_sw_params_set_silence_size failed: %s\n"),
|
||||||
|
snd_strerror(err));
|
||||||
|
}
|
||||||
|
if ((err =
|
||||||
|
snd_pcm_sw_params_set_silence_size(AlsaPCMHandle, sw_params,
|
||||||
|
boundary)) < 0) {
|
||||||
|
Error(_("audio: snd_pcm_sw_params_set_silence_size failed: %s\n"),
|
||||||
|
snd_strerror(err));
|
||||||
|
}
|
||||||
|
if ((err = snd_pcm_sw_params(AlsaPCMHandle, sw_params)) < 0) {
|
||||||
|
Error(_("audio: snd_pcm_sw_params failed: %s\n"),
|
||||||
|
snd_strerror(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// update buffer
|
// update buffer
|
||||||
|
|
||||||
snd_pcm_get_params(AlsaPCMHandle, &buffer_size, &period_size);
|
snd_pcm_get_params(AlsaPCMHandle, &buffer_size, &period_size);
|
||||||
@ -954,6 +1128,7 @@ static int OssAddToRingbuffer(const void *samples, int count)
|
|||||||
if (n != count) {
|
if (n != count) {
|
||||||
Error(_("audio/oss: can't place %d samples in ring buffer\n"), count);
|
Error(_("audio/oss: can't place %d samples in ring buffer\n"), count);
|
||||||
// too many bytes are lost
|
// too many bytes are lost
|
||||||
|
// FIXME: should skip more, longer skip, but less often?
|
||||||
}
|
}
|
||||||
// Update audio clock
|
// Update audio clock
|
||||||
AudioPTS +=
|
AudioPTS +=
|
||||||
@ -1375,12 +1550,59 @@ static void *AudioPlayHandlerThread(void *dummy)
|
|||||||
Debug(3, "audio: wait on start condition\n");
|
Debug(3, "audio: wait on start condition\n");
|
||||||
pthread_mutex_lock(&AudioMutex);
|
pthread_mutex_lock(&AudioMutex);
|
||||||
AudioRunning = 0;
|
AudioRunning = 0;
|
||||||
|
#ifndef SEARCH_HDMI_BUG
|
||||||
do {
|
do {
|
||||||
pthread_cond_wait(&AudioStartCond, &AudioMutex);
|
pthread_cond_wait(&AudioStartCond, &AudioMutex);
|
||||||
// cond_wait can return, without signal!
|
// cond_wait can return, without signal!
|
||||||
} while (!AudioRunning);
|
} while (!AudioRunning);
|
||||||
|
#else
|
||||||
|
usleep(1 * 1000);
|
||||||
|
AudioRunning = 1;
|
||||||
|
#endif
|
||||||
pthread_mutex_unlock(&AudioMutex);
|
pthread_mutex_unlock(&AudioMutex);
|
||||||
|
|
||||||
|
#ifdef SEARCH_HDMI_BUG2
|
||||||
|
if (atomic_read(&AudioRingFilled) > 1) {
|
||||||
|
int sample_rate;
|
||||||
|
int channels;
|
||||||
|
|
||||||
|
// skip all sample changes between
|
||||||
|
while (atomic_read(&AudioRingFilled) > 1) {
|
||||||
|
Debug(3, "audio: skip ring buffer\n");
|
||||||
|
AudioRingRead = (AudioRingRead + 1) % AUDIO_RING_MAX;
|
||||||
|
atomic_dec(&AudioRingFilled);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ALSA
|
||||||
|
// FIXME: flush only if there is something to flush
|
||||||
|
AlsaFlushBuffers();
|
||||||
|
|
||||||
|
sample_rate = AudioRing[AudioRingRead].SampleRate;
|
||||||
|
channels = AudioRing[AudioRingRead].Channels;
|
||||||
|
Debug(3, "audio: thread channels %d sample-rate %d hz\n", channels,
|
||||||
|
sample_rate);
|
||||||
|
|
||||||
|
if (AlsaSetup(&sample_rate, &channels)) {
|
||||||
|
Error(_("audio: can't set channels %d sample-rate %d hz\n"),
|
||||||
|
channels, sample_rate);
|
||||||
|
}
|
||||||
|
Debug(3, "audio: thread channels %d sample-rate %d hz\n",
|
||||||
|
AudioChannels, AudioSampleRate);
|
||||||
|
if (1) {
|
||||||
|
int16_t buf[6144 / 2];
|
||||||
|
|
||||||
|
buf[0] = htole16(0xF872); // iec 61937 sync word
|
||||||
|
buf[1] = htole16(0x4E1F);
|
||||||
|
buf[2] = htole16((7 << 5) << 8 | 0x00);
|
||||||
|
buf[3] = htole16(0x0000);
|
||||||
|
memset(buf + 4, 0, 6144 - 8);
|
||||||
|
|
||||||
|
AlsaEnqueue(buf, 6144);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Debug(3, "audio: play start\n");
|
Debug(3, "audio: play start\n");
|
||||||
#ifdef USE_ALSA
|
#ifdef USE_ALSA
|
||||||
AlsaThread();
|
AlsaThread();
|
||||||
@ -1406,6 +1628,8 @@ static void AudioInitThread(void)
|
|||||||
pthread_yield();
|
pthread_yield();
|
||||||
} while (!AlsaPCMHandle);
|
} while (!AlsaPCMHandle);
|
||||||
#endif
|
#endif
|
||||||
|
pthread_yield();
|
||||||
|
usleep(5 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1550,6 +1774,10 @@ int AudioSetup(int *freq, int *channels)
|
|||||||
// FIXME: set flag invalid setup
|
// FIXME: set flag invalid setup
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#if defined(SEARCH_HDMI_BUG) || defined(SEARCH_HDMI_BUG2)
|
||||||
|
// FIXME: need to store possible combination and report this
|
||||||
|
return AudioRingAdd(*freq, *channels);
|
||||||
|
#endif
|
||||||
#ifdef USE_ALSA
|
#ifdef USE_ALSA
|
||||||
return AlsaSetup(freq, channels);
|
return AlsaSetup(freq, channels);
|
||||||
#endif
|
#endif
|
||||||
@ -1577,6 +1805,9 @@ void AudioInit(void)
|
|||||||
int freq;
|
int freq;
|
||||||
int chan;
|
int chan;
|
||||||
|
|
||||||
|
#ifdef SEARCH_HDMI_BUG2
|
||||||
|
AudioRingInit();
|
||||||
|
#endif
|
||||||
#ifdef USE_ALSA
|
#ifdef USE_ALSA
|
||||||
AlsaInit();
|
AlsaInit();
|
||||||
#endif
|
#endif
|
||||||
@ -1609,6 +1840,9 @@ void AudioExit(void)
|
|||||||
#ifdef USE_OSS
|
#ifdef USE_OSS
|
||||||
OssExit();
|
OssExit();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SEARCH_HDMI_BUG2
|
||||||
|
AudioRingExit();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AUDIO_TEST
|
#ifdef AUDIO_TEST
|
||||||
|
Loading…
Reference in New Issue
Block a user