Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
52867 views
1
/*
2
* Linux audio play interface
3
* Copyright (c) 2000, 2001 Fabrice Bellard
4
*
5
* This file is part of FFmpeg.
6
*
7
* FFmpeg is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* FFmpeg is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with FFmpeg; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include "config.h"
23
24
#include <stdint.h>
25
26
#if HAVE_SOUNDCARD_H
27
#include <soundcard.h>
28
#else
29
#include <sys/soundcard.h>
30
#endif
31
32
#if HAVE_UNISTD_H
33
#include <unistd.h>
34
#endif
35
#include <fcntl.h>
36
#include <sys/ioctl.h>
37
38
#include "libavutil/internal.h"
39
#include "libavutil/opt.h"
40
#include "libavutil/time.h"
41
42
#include "libavcodec/avcodec.h"
43
44
#include "avdevice.h"
45
#include "libavformat/internal.h"
46
47
#include "oss.h"
48
49
static int audio_read_header(AVFormatContext *s1)
50
{
51
OSSAudioData *s = s1->priv_data;
52
AVStream *st;
53
int ret;
54
55
st = avformat_new_stream(s1, NULL);
56
if (!st) {
57
return AVERROR(ENOMEM);
58
}
59
60
ret = ff_oss_audio_open(s1, 0, s1->filename);
61
if (ret < 0) {
62
return AVERROR(EIO);
63
}
64
65
/* take real parameters */
66
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
67
st->codec->codec_id = s->codec_id;
68
st->codec->sample_rate = s->sample_rate;
69
st->codec->channels = s->channels;
70
71
avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
72
return 0;
73
}
74
75
static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
76
{
77
OSSAudioData *s = s1->priv_data;
78
int ret, bdelay;
79
int64_t cur_time;
80
struct audio_buf_info abufi;
81
82
if ((ret=av_new_packet(pkt, s->frame_size)) < 0)
83
return ret;
84
85
ret = read(s->fd, pkt->data, pkt->size);
86
if (ret <= 0){
87
av_packet_unref(pkt);
88
pkt->size = 0;
89
if (ret<0) return AVERROR(errno);
90
else return AVERROR_EOF;
91
}
92
pkt->size = ret;
93
94
/* compute pts of the start of the packet */
95
cur_time = av_gettime();
96
bdelay = ret;
97
if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) {
98
bdelay += abufi.bytes;
99
}
100
/* subtract time represented by the number of bytes in the audio fifo */
101
cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels);
102
103
/* convert to wanted units */
104
pkt->pts = cur_time;
105
106
if (s->flip_left && s->channels == 2) {
107
int i;
108
short *p = (short *) pkt->data;
109
110
for (i = 0; i < ret; i += 4) {
111
*p = ~*p;
112
p += 2;
113
}
114
}
115
return 0;
116
}
117
118
static int audio_read_close(AVFormatContext *s1)
119
{
120
OSSAudioData *s = s1->priv_data;
121
122
ff_oss_audio_close(s);
123
return 0;
124
}
125
126
static const AVOption options[] = {
127
{ "sample_rate", "", offsetof(OSSAudioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
128
{ "channels", "", offsetof(OSSAudioData, channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
129
{ NULL },
130
};
131
132
static const AVClass oss_demuxer_class = {
133
.class_name = "OSS demuxer",
134
.item_name = av_default_item_name,
135
.option = options,
136
.version = LIBAVUTIL_VERSION_INT,
137
.category = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,
138
};
139
140
AVInputFormat ff_oss_demuxer = {
141
.name = "oss",
142
.long_name = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) capture"),
143
.priv_data_size = sizeof(OSSAudioData),
144
.read_header = audio_read_header,
145
.read_packet = audio_read_packet,
146
.read_close = audio_read_close,
147
.flags = AVFMT_NOFILE,
148
.priv_class = &oss_demuxer_class,
149
};
150
151