⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oss.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / linux_oss audio render module * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *		 */#if defined(__DARWIN__) || defined(__APPLE__)#include <soundcard.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <dirent.h>#include <sys/stat.h>#include <string.h>#else#include <sys/ioctl.h>#include <unistd.h>#include <fcntl.h>#ifdef OSS_FIX_INC#include <soundcard.h>#else#include <sys/soundcard.h>#endif#endif#include <gpac/modules/audio_out.h>#define OSS_AUDIO_DEVICE	"/dev/dsp"typedef struct {	int audio_dev, sr, nb_ch;	u32 buf_size, delay, num_buffers, total_duration;	u32 force_sr;	char *wav_buf;} OSSContext;#define OSSCTX()	OSSContext *ctx = (OSSContext *)dr->opaque;static GF_Err OSS_Setup(GF_AudioOutput*dr, void *os_handle, u32 num_buffers, u32 total_duration){	int audio;	const char *opt;	OSSCTX();	opt = gf_modules_get_option((GF_BaseInterface *)dr, "OSS", "ForceSampleRate");	if (opt) ctx->force_sr = atoi(opt);	/*open OSS in non-blocking mode*/	audio = open(OSS_AUDIO_DEVICE, 0);	if (audio < 0) {	  GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[OSS] Cannot open audio device\n"));	  return GF_NOT_SUPPORTED;	}	/*set blocking mode back*/	//fcntl(audio, F_SETFL, fcntl(audio, F_GETFL) & ~FNDELAY);	ctx->audio_dev=audio;	ctx->num_buffers = num_buffers;	ctx->total_duration = total_duration;	return GF_OK;}static void OSS_Shutdown(GF_AudioOutput*dr){	OSSCTX();	ioctl(ctx->audio_dev,SNDCTL_DSP_RESET);	close(ctx->audio_dev);	if (ctx->wav_buf) free(ctx->wav_buf);	ctx->wav_buf = NULL;}static GF_Err OSS_ConfigureOutput(GF_AudioOutput*dr, u32 *SampleRate, u32 *NbChannels, u32 *nbBitsPerSample, u32 channel_cfg){	int format, blockalign, nb_bufs, frag_spec;	long flags;	OSSCTX();	if (!ctx) return GF_BAD_PARAM;	/* reset and reopen audio-device */	ioctl(ctx->audio_dev,SNDCTL_DSP_RESET);	close(ctx->audio_dev);	if (ctx->wav_buf) free(ctx->wav_buf);	ctx->wav_buf = NULL;	ctx->audio_dev=open(OSS_AUDIO_DEVICE,O_WRONLY|O_NONBLOCK);	if (!ctx->audio_dev) return GF_IO_ERR;	/* Make the file descriptor use blocking writes with fcntl() so that 	 we don't have to handle sleep() ourselves*/	flags = fcntl(ctx->audio_dev, F_GETFL);	flags &= ~O_NONBLOCK;	if (fcntl(ctx->audio_dev, F_SETFL, flags) < 0 ) return GF_IO_ERR;	ctx->nb_ch = (int) (*NbChannels);	if (ioctl(ctx->audio_dev, SNDCTL_DSP_CHANNELS, &ctx->nb_ch)==-1) return GF_IO_ERR;	blockalign = ctx->nb_ch;	if ((*nbBitsPerSample) == 16) {	  blockalign *= 2;	  format = AFMT_S16_LE;	} else {	  format = AFMT_S8;	}	if(ioctl(ctx->audio_dev, SNDCTL_DSP_SETFMT,&format)==-1) return GF_IO_ERR;        ctx->sr = (*SampleRate);	if(ioctl(ctx->audio_dev, SNDCTL_DSP_SPEED,&ctx->sr)==-1) return GF_IO_ERR;	frag_spec = 7;	ctx->buf_size = 0x01 << frag_spec;	nb_bufs = ctx->num_buffers ? ctx->num_buffers : 8;	if (nb_bufs<8) nb_bufs = 8;	ctx->delay = (1000*ctx->buf_size) / (*SampleRate * blockalign);	frag_spec = ((nb_bufs<<16) & 0xFFFF0000) | frag_spec;		ctx->delay = (1000*ctx->buf_size*nb_bufs) / (*SampleRate * blockalign);	if ( ioctl(ctx->audio_dev, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0 ) return GF_IO_ERR;	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[OSS] setup %d buffers %d bytes each (%d ms buffer delay)", nb_bufs, ctx->buf_size, ctx->delay));	ctx->wav_buf = realloc(ctx->wav_buf, ctx->buf_size*sizeof(char));	if(!ctx->wav_buf) return GF_OUT_OF_MEM;	memset(ctx->wav_buf, 0, ctx->buf_size*sizeof(char));	return GF_OK;}static void OSS_WriteAudio(GF_AudioOutput*dr){	u32 written;	OSSCTX();	written = dr->FillBuffer(dr->audio_renderer, ctx->wav_buf, ctx->buf_size);	/*this will also perform sleep*/	write(ctx->audio_dev, ctx->wav_buf, written);}static void OSS_SetVolume(GF_AudioOutput*dr, u32 Volume) {}static void OSS_SetPan(GF_AudioOutput*dr, u32 Pan) {}static void OSS_SetPriority(GF_AudioOutput*dr, u32 Priority) {}static u32 OSS_GetAudioDelay(GF_AudioOutput*dr){  OSSCTX()  return ctx->delay;}/* * to get the best matching samplerate the oss-device can be set up * with the desired sr. if not supported the returned value contains the * best matching sr. * * todo: supported samplerate could depend on nb_channels and format */static GF_Err OSS_QueryOutputSampleRate(GF_AudioOutput*dr, u32 *desired_sr, u32 *NbChannels, u32 *nbBitsPerSample){#ifdef FORCE_SR_LIMIT  *NbChannels = 2;  if (!( *desired_sr % 11025)) return GF_OK;  if (*desired_sr<22050) *desired_sr = 22050;  else *desired_sr = 44100;  return GF_OK;#else	/* reset and reopen audio-device */	int i;	OSSCTX();	if (ctx->force_sr) {	  *desired_sr = ctx->force_sr;	  return GF_OK;	}	i=*desired_sr;	if(ioctl(ctx->audio_dev, SNDCTL_DSP_SPEED,&i)==-1) return GF_IO_ERR;	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[OSS] uses samplerate %d for desired sr %d\n", i, *desired_sr));	*desired_sr = i;	i = *NbChannels;	if(ioctl(ctx->audio_dev,SNDCTL_DSP_CHANNELS, &i)==-1) return GF_IO_ERR;	GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[OSS] uses %d channels for %d desired ones\n", i, *NbChannels));	*NbChannels = i;	if(ioctl(ctx->audio_dev, SNDCTL_DSP_SPEED,&ctx->sr)==-1) return GF_OK;	if(ioctl(ctx->audio_dev,SNDCTL_DSP_CHANNELS, &ctx->nb_ch)==-1) return GF_OK;	return GF_OK;#endif}void *NewOSSRender(){	OSSContext *ctx;	GF_AudioOutput*driv;	ctx = malloc(sizeof(OSSContext));	if(!ctx)		return NULL;	memset(ctx, 0, sizeof(OSSContext));	driv = malloc(sizeof(GF_AudioOutput));	if(!driv)	{		free(ctx);		ctx=NULL;		return NULL;	}	memset(driv, 0, sizeof(GF_AudioOutput));	driv->opaque = ctx;	driv->SelfThreaded = 0;	driv->Setup = OSS_Setup;	driv->Shutdown = OSS_Shutdown;	driv->ConfigureOutput = OSS_ConfigureOutput;	driv->GetAudioDelay = OSS_GetAudioDelay;	driv->SetVolume = OSS_SetVolume;	driv->SetPan = OSS_SetPan;	driv->SetPriority = OSS_SetPriority;	driv->QueryOutputSampleRate = OSS_QueryOutputSampleRate;	driv->WriteAudio = OSS_WriteAudio;	GF_REGISTER_MODULE_INTERFACE(driv, GF_AUDIO_OUTPUT_INTERFACE, "OSS Audio Output", "gpac distribution");	return driv;}void DeleteOSSRender(void *ifce){	GF_AudioOutput*dr = (GF_AudioOutput*) ifce;	OSSContext *ctx = (OSSContext *)dr->opaque;	free(ctx);	free(dr);}/* * ******************************************************************** * interface */Bool QueryInterface(u32 InterfaceType){	if (InterfaceType == GF_AUDIO_OUTPUT_INTERFACE) 		return 1;	return 0;}GF_BaseInterface *LoadInterface(u32 InterfaceType){	if (InterfaceType == GF_AUDIO_OUTPUT_INTERFACE) 		return NewOSSRender();	return NULL;}void ShutdownInterface(GF_BaseInterface *ifce){	if (ifce->InterfaceType==GF_AUDIO_OUTPUT_INTERFACE)		DeleteOSSRender((GF_AudioOutput*)ifce);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -