Merge remote-tracking branch 'luzero/pulse'
* luzero/pulse: pulse: set the device from the avformat filename Conflicts: libavdevice/pulse.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
commit
c2553a5585
@ -41,11 +41,11 @@ typedef struct PulseData {
|
|||||||
AVClass *class;
|
AVClass *class;
|
||||||
char *server;
|
char *server;
|
||||||
char *name;
|
char *name;
|
||||||
char *dev;
|
|
||||||
char *stream_name;
|
char *stream_name;
|
||||||
int sample_rate;
|
int sample_rate;
|
||||||
int channels;
|
int channels;
|
||||||
int frame_size;
|
int frame_size;
|
||||||
|
int fragment_size;
|
||||||
pa_simple *s;
|
pa_simple *s;
|
||||||
int64_t pts;
|
int64_t pts;
|
||||||
} PulseData;
|
} PulseData;
|
||||||
@ -72,6 +72,7 @@ static av_cold int pulse_read_header(AVFormatContext *s,
|
|||||||
{
|
{
|
||||||
PulseData *pd = s->priv_data;
|
PulseData *pd = s->priv_data;
|
||||||
AVStream *st;
|
AVStream *st;
|
||||||
|
char *device = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
enum CodecID codec_id =
|
enum CodecID codec_id =
|
||||||
s->audio_codec_id == CODEC_ID_NONE ? DEFAULT_CODEC_ID : s->audio_codec_id;
|
s->audio_codec_id == CODEC_ID_NONE ? DEFAULT_CODEC_ID : s->audio_codec_id;
|
||||||
@ -88,12 +89,16 @@ static av_cold int pulse_read_header(AVFormatContext *s,
|
|||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr.fragsize = pd->frame_size * 4;
|
attr.fragsize = pd->fragment_size;
|
||||||
|
|
||||||
|
if (strcmp(s->filename, "default"))
|
||||||
|
device = s->filename;
|
||||||
|
|
||||||
pd->s = pa_simple_new(pd->server, pd->name,
|
pd->s = pa_simple_new(pd->server, pd->name,
|
||||||
PA_STREAM_RECORD,
|
PA_STREAM_RECORD,
|
||||||
pd->dev, pd->stream_name, &ss,
|
device, pd->stream_name, &ss,
|
||||||
NULL, &attr, &ret);
|
NULL, &attr, &ret);
|
||||||
|
|
||||||
if (!pd->s) {
|
if (!pd->s) {
|
||||||
av_log(s, AV_LOG_ERROR, "pa_simple_new failed: %s\n",
|
av_log(s, AV_LOG_ERROR, "pa_simple_new failed: %s\n",
|
||||||
pa_strerror(ret));
|
pa_strerror(ret));
|
||||||
@ -106,6 +111,8 @@ static av_cold int pulse_read_header(AVFormatContext *s,
|
|||||||
st->codec->channels = pd->channels;
|
st->codec->channels = pd->channels;
|
||||||
av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
|
av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
|
||||||
|
|
||||||
|
pd->pts = AV_NOPTS_VALUE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +120,7 @@ static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
{
|
{
|
||||||
PulseData *pd = s->priv_data;
|
PulseData *pd = s->priv_data;
|
||||||
int res;
|
int res;
|
||||||
pa_usec_t latency, cur;
|
pa_usec_t latency;
|
||||||
uint64_t frame_duration =
|
uint64_t frame_duration =
|
||||||
(pd->frame_size*1000000LL)/(pd->sample_rate * pd->channels);
|
(pd->frame_size*1000000LL)/(pd->sample_rate * pd->channels);
|
||||||
|
|
||||||
@ -121,8 +128,6 @@ static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = pa_rtclock_now();
|
|
||||||
|
|
||||||
if ((pa_simple_read(pd->s, pkt->data, pkt->size, &res)) < 0) {
|
if ((pa_simple_read(pd->s, pkt->data, pkt->size, &res)) < 0) {
|
||||||
av_log(s, AV_LOG_ERROR, "pa_simple_read failed: %s\n",
|
av_log(s, AV_LOG_ERROR, "pa_simple_read failed: %s\n",
|
||||||
pa_strerror(res));
|
pa_strerror(res));
|
||||||
@ -136,16 +141,12 @@ static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
return AVERROR(EIO);
|
return AVERROR(EIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pd->pts) {
|
if (pd->pts == AV_NOPTS_VALUE) {
|
||||||
pd->pts -= latency;
|
pd->pts = -latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
pd->pts += frame_duration;
|
pd->pts += frame_duration;
|
||||||
|
|
||||||
av_log(s, AV_LOG_DEBUG, "%"PRId64" time %"PRId64","
|
|
||||||
" latency %"PRId64", %"PRId64"\n",
|
|
||||||
av_gettime(), cur, latency, pd->pts);
|
|
||||||
|
|
||||||
pkt->pts = pd->pts;
|
pkt->pts = pd->pts;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -162,13 +163,20 @@ static av_cold int pulse_close(AVFormatContext *s)
|
|||||||
#define D AV_OPT_FLAG_DECODING_PARAM
|
#define D AV_OPT_FLAG_DECODING_PARAM
|
||||||
|
|
||||||
static const AVOption options[] = {
|
static const AVOption options[] = {
|
||||||
{ "server", "pulse server name", OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
|
{ "server", "pulse server name",
|
||||||
{ "name", "application name", OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, D },
|
OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
|
||||||
{ "dev", "device to use", OFFSET(dev), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
|
{ "name", "application name",
|
||||||
{ "stream_name", "stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = "record"}, 0, 0, D },
|
OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, D },
|
||||||
{ "sample_rate", "", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.dbl = 48000}, 1, INT_MAX, D },
|
{ "stream_name", "stream description",
|
||||||
{ "channels", "", OFFSET(channels), AV_OPT_TYPE_INT, {.dbl = 2}, 1, INT_MAX, D },
|
OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = "record"}, 0, 0, D },
|
||||||
{ "frame_size", "", OFFSET(frame_size), AV_OPT_TYPE_INT, {.dbl = 1024}, 1, INT_MAX, D },
|
{ "sample_rate", "",
|
||||||
|
OFFSET(sample_rate), AV_OPT_TYPE_INT, {.dbl = 48000}, 1, INT_MAX, D },
|
||||||
|
{ "channels", "",
|
||||||
|
OFFSET(channels), AV_OPT_TYPE_INT, {.dbl = 2}, 1, INT_MAX, D },
|
||||||
|
{ "frame_size", "",
|
||||||
|
OFFSET(frame_size), AV_OPT_TYPE_INT, {.dbl = 1024}, 1, INT_MAX, D },
|
||||||
|
{ "fragment_size", "buffering size, affects latency and cpu usage",
|
||||||
|
OFFSET(fragment_size), AV_OPT_TYPE_INT, {.dbl = -1}, -1, INT_MAX, D },
|
||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user