Luca Abeni <[EMAIL PROTECTED]> added the comment:
Alsa support: common functions
----------
status: new -> open
substatus: new -> needs_changes
______________________________________________________
FFmpeg issue tracker <[EMAIL PROTECTED]>
<https://roundup.mplayerhq.hu/roundup/ffmpeg/issue247>
______________________________________________________
#include "avformat.h"
#include <alsa/asoundlib.h>
#include "alsa-audio.h"
static int alsa_codec_id(int codec_id)
{
switch(codec_id) {
case CODEC_ID_PCM_S16LE:
return SND_PCM_FORMAT_S16_LE;
case CODEC_ID_PCM_S16BE:
return SND_PCM_FORMAT_S16_BE;
default:
return -1;
}
}
int ff_alsa_supported_codec_id(enum CodecID codec_id)
{
switch (codec_id) {
case DEFAULT_CODEC_ID:
return 1;
default:
return 0;
}
}
int ff_alsa_open(AVFormatContext *ctx, int mode)
{
AlsaData *s = ctx->priv_data;
const char *audio_device;
int res, flags = 0;
snd_pcm_t *h;
snd_pcm_hw_params_t *hw_params;
if (ctx->filename[0] == 0) {
audio_device = DEFAULT_DEVICE;
} else {
audio_device = ctx->filename;
}
if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
flags = O_NONBLOCK;
}
res = snd_pcm_open(&h, audio_device, mode, flags);
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "cannot open audio device %s (%s)\n",
audio_device, snd_strerror(res));
return AVERROR_IO;
}
res = snd_pcm_hw_params_malloc(&hw_params);
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n",
snd_strerror(res));
goto fail1;
}
res = snd_pcm_hw_params_any(h, hw_params);
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "cannot initialize hardware parameter structure (%s)\n",
snd_strerror(res));
goto fail;
}
res = snd_pcm_hw_params_set_access(h, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "cannot set access type (%s)\n",
snd_strerror(res));
goto fail;
}
res = snd_pcm_hw_params_set_format(h, hw_params, alsa_codec_id(s->codec_id));
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "cannot set sample format %d %d (%s)\n",
s->codec_id, alsa_codec_id(s->codec_id), snd_strerror(res));
goto fail;
}
res = snd_pcm_hw_params_set_rate_near(h, hw_params, &s->sample_rate, 0);
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "cannot set sample rate (%s)\n",
snd_strerror(res));
goto fail;
}
res = snd_pcm_hw_params_set_period_size(h, hw_params, AUDIO_BLOCK_SIZE / (av_get_bits_per_sample(s->codec_id) / 8 * s->channels), 0);
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "cannot set ALSA period size (%s)\n",
snd_strerror(res));
goto fail;
}
s->frame_size = AUDIO_BLOCK_SIZE;
res = snd_pcm_hw_params_set_channels(h, hw_params, s->channels);
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "cannot set channel count to %d (%s)\n",
s->channels, snd_strerror(res));
goto fail;
}
res = snd_pcm_hw_params(h, hw_params);
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "cannot set parameters (%s)\n",
snd_strerror(res));
goto fail;
}
snd_pcm_hw_params_free(hw_params);
s->h = h;
return 0;
fail:
snd_pcm_hw_params_free(hw_params);
fail1:
snd_pcm_close(h);
return AVERROR_IO;
}
int ff_alsa_close(AlsaData *s)
{
snd_pcm_close(s->h);
return 0;
}
int ff_alsa_xrun_recover(AVFormatContext *s1, int err)
{
AlsaData *s = s1->priv_data;
snd_pcm_t *handle = s->h;
av_log(s1, AV_LOG_ERROR, "XRUN!!!\n");
if (err == -EPIPE) {
err = snd_pcm_prepare(handle);
if (err < 0) {
av_log(NULL, AV_LOG_ERROR, "cannot recover from underrun (snd_pcm_prepare failed: %s)\n", snd_strerror(err));
return 0;
}
} else if (err == -ESTRPIPE) {
av_log(NULL, AV_LOG_ERROR, "-ESTPIPE... Unsupported!\n");
return -1;
}
return err;
}