You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
6.8KB

  1. /*
  2. * Linux audio play and grab interface
  3. * Copyright (c) 2000, 2001 Gerard Lantau.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include "avformat.h"
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <linux/soundcard.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <sys/ioctl.h>
  27. #include <sys/mman.h>
  28. #include <sys/time.h>
  29. const char *audio_device = "/dev/dsp";
  30. #define AUDIO_BLOCK_SIZE 4096
  31. typedef struct {
  32. int fd;
  33. int sample_rate;
  34. int channels;
  35. int frame_size; /* in bytes ! */
  36. int codec_id;
  37. UINT8 buffer[AUDIO_BLOCK_SIZE];
  38. int buffer_ptr;
  39. } AudioData;
  40. static int audio_open(AudioData *s, int is_output)
  41. {
  42. int audio_fd;
  43. int tmp, err;
  44. /* open linux audio device */
  45. if (is_output)
  46. audio_fd = open(audio_device, O_WRONLY);
  47. else
  48. audio_fd = open(audio_device, O_RDONLY);
  49. if (audio_fd < 0) {
  50. perror(audio_device);
  51. return -EIO;
  52. }
  53. /* non blocking mode */
  54. fcntl(audio_fd, F_SETFL, O_NONBLOCK);
  55. s->frame_size = AUDIO_BLOCK_SIZE;
  56. #if 0
  57. tmp = (NB_FRAGMENTS << 16) | FRAGMENT_BITS;
  58. err = ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
  59. if (err < 0) {
  60. perror("SNDCTL_DSP_SETFRAGMENT");
  61. }
  62. #endif
  63. /* select format : favour native format */
  64. err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
  65. #ifdef WORDS_BIGENDIAN
  66. if (tmp & AFMT_S16_BE) {
  67. tmp = AFMT_S16_BE;
  68. } else if (tmp & AFMT_S16_LE) {
  69. tmp = AFMT_S16_LE;
  70. } else {
  71. tmp = 0;
  72. }
  73. #else
  74. if (tmp & AFMT_S16_LE) {
  75. tmp = AFMT_S16_LE;
  76. } else if (tmp & AFMT_S16_BE) {
  77. tmp = AFMT_S16_BE;
  78. } else {
  79. tmp = 0;
  80. }
  81. #endif
  82. switch(tmp) {
  83. case AFMT_S16_LE:
  84. s->codec_id = CODEC_ID_PCM_S16LE;
  85. break;
  86. case AFMT_S16_BE:
  87. s->codec_id = CODEC_ID_PCM_S16BE;
  88. break;
  89. default:
  90. fprintf(stderr, "Soundcard does not support 16 bit sample format\n");
  91. close(audio_fd);
  92. return -EIO;
  93. }
  94. err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
  95. if (err < 0) {
  96. perror("SNDCTL_DSP_SETFMT");
  97. goto fail;
  98. }
  99. tmp = (s->channels == 2);
  100. err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
  101. if (err < 0) {
  102. perror("SNDCTL_DSP_STEREO");
  103. goto fail;
  104. }
  105. tmp = s->sample_rate;
  106. err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
  107. if (err < 0) {
  108. perror("SNDCTL_DSP_SPEED");
  109. goto fail;
  110. }
  111. s->sample_rate = tmp; /* store real sample rate */
  112. s->fd = audio_fd;
  113. return 0;
  114. fail:
  115. close(audio_fd);
  116. return -EIO;
  117. }
  118. static int audio_close(AudioData *s)
  119. {
  120. close(s->fd);
  121. return 0;
  122. }
  123. /* sound output support */
  124. static int audio_write_header(AVFormatContext *s1)
  125. {
  126. AudioData *s;
  127. AVStream *st;
  128. int ret;
  129. s = av_mallocz(sizeof(AudioData));
  130. if (!s)
  131. return -ENOMEM;
  132. s1->priv_data = s;
  133. st = s1->streams[0];
  134. s->sample_rate = st->codec.sample_rate;
  135. s->channels = st->codec.channels;
  136. ret = audio_open(s, 1);
  137. if (ret < 0) {
  138. free(s);
  139. return -EIO;
  140. } else {
  141. return 0;
  142. }
  143. }
  144. static int audio_write_packet(AVFormatContext *s1, int stream_index,
  145. UINT8 *buf, int size, int force_pts)
  146. {
  147. AudioData *s = s1->priv_data;
  148. int len, ret;
  149. while (size > 0) {
  150. len = AUDIO_BLOCK_SIZE - s->buffer_ptr;
  151. if (len > size)
  152. len = size;
  153. memcpy(s->buffer + s->buffer_ptr, buf, len);
  154. s->buffer_ptr += len;
  155. if (s->buffer_ptr >= AUDIO_BLOCK_SIZE) {
  156. for(;;) {
  157. ret = write(s->fd, s->buffer, AUDIO_BLOCK_SIZE);
  158. if (ret != 0)
  159. break;
  160. if (ret < 0 && (errno != EAGAIN && errno != EINTR))
  161. return -EIO;
  162. }
  163. s->buffer_ptr = 0;
  164. }
  165. buf += len;
  166. size -= len;
  167. }
  168. return 0;
  169. }
  170. static int audio_write_trailer(AVFormatContext *s1)
  171. {
  172. AudioData *s = s1->priv_data;
  173. audio_close(s);
  174. free(s);
  175. return 0;
  176. }
  177. /* grab support */
  178. static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
  179. {
  180. AudioData *s;
  181. AVStream *st;
  182. int ret;
  183. if (!ap || ap->sample_rate <= 0 || ap->channels <= 0)
  184. return -1;
  185. s = av_mallocz(sizeof(AudioData));
  186. if (!s)
  187. return -ENOMEM;
  188. st = av_mallocz(sizeof(AVStream));
  189. if (!st) {
  190. free(s);
  191. return -ENOMEM;
  192. }
  193. s1->priv_data = s;
  194. s1->nb_streams = 1;
  195. s1->streams[0] = st;
  196. s->sample_rate = ap->sample_rate;
  197. s->channels = ap->channels;
  198. ret = audio_open(s, 0);
  199. if (ret < 0) {
  200. free(st);
  201. free(s);
  202. return -EIO;
  203. } else {
  204. /* take real parameters */
  205. st->codec.codec_type = CODEC_TYPE_AUDIO;
  206. st->codec.codec_id = s->codec_id;
  207. st->codec.sample_rate = s->sample_rate;
  208. st->codec.channels = s->channels;
  209. return 0;
  210. }
  211. }
  212. static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
  213. {
  214. AudioData *s = s1->priv_data;
  215. int ret;
  216. if (av_new_packet(pkt, s->frame_size) < 0)
  217. return -EIO;
  218. for(;;) {
  219. ret = read(s->fd, pkt->data, pkt->size);
  220. if (ret > 0)
  221. break;
  222. if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
  223. av_free_packet(pkt);
  224. pkt->size = 0;
  225. return 0;
  226. }
  227. if (!(ret == 0 || (ret == -1 && (errno == EAGAIN || errno == EINTR)))) {
  228. av_free_packet(pkt);
  229. return -EIO;
  230. }
  231. }
  232. pkt->size = ret;
  233. return 0;
  234. }
  235. static int audio_read_close(AVFormatContext *s1)
  236. {
  237. AudioData *s = s1->priv_data;
  238. audio_close(s);
  239. free(s);
  240. return 0;
  241. }
  242. AVFormat audio_device_format = {
  243. "audio_device",
  244. "audio grab and output",
  245. "",
  246. "",
  247. /* XXX: we make the assumption that the soundcard accepts this format */
  248. /* XXX: find better solution with "preinit" method, needed also in
  249. other formats */
  250. #ifdef WORDS_BIGENDIAN
  251. CODEC_ID_PCM_S16BE,
  252. #else
  253. CODEC_ID_PCM_S16LE,
  254. #endif
  255. CODEC_ID_NONE,
  256. audio_write_header,
  257. audio_write_packet,
  258. audio_write_trailer,
  259. audio_read_header,
  260. audio_read_packet,
  261. audio_read_close,
  262. NULL,
  263. AVFMT_NOFILE,
  264. };