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

📄 ao_dsound.c

📁 DawnLightPlayer,一个新的基于ffmpeg的全功能播放器
💻 C
字号:
/********************************************** * Dawn Light Player * *   ao_dsound.c * * Created by qwdu * 17:44:23 03/18/08 CST * * $Id: ao_dsound.c 168 2008-03-21 02:50:01Z kf701 $ **********************************************/#if ENABLE_AO_DSOUND#include <windows.h>#include <dsound.h>#include <math.h>#include "avoutput.h"#include "global.h"static pthread_mutex_t ao_mutex;static void ao_lock_init(){	pthread_mutex_init(&ao_mutex,NULL);}static void ao_lock_free(){	pthread_mutex_destroy(&ao_mutex);}static void ao_lock(){	pthread_mutex_lock(&ao_mutex);}static void ao_unlock(){	pthread_mutex_unlock(&ao_mutex);}#ifndef _WAVEFORMATEXTENSIBLE_typedef struct{	WAVEFORMATEX Format;	union	{		WORD wValidBitsPerSample;		WORD wSamplesPerBlock;		WORD wReserved;	} Samples;	DWORD dwChannelMask;	GUID SubFormat;} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;#endifstatic HINSTANCE hdsound_dll = NULL;static LPDIRECTSOUND hds = NULL;static LPDIRECTSOUNDBUFFER hdspribuf = NULL;static LPDIRECTSOUNDBUFFER hdsbuf = NULL;static int buffer_size = 0;static int write_offset = 0;static int min_free_space = 0;static int device_num = 0;static GUID device;static void dsound_reset(void){	ao_lock();	IDirectSoundBuffer_Stop(hdsbuf);	IDirectSoundBuffer_SetCurrentPosition(hdsbuf, 0);	write_offset=0;	ao_unlock();}static void dsound_pause(void){	ao_lock();	IDirectSoundBuffer_Stop(hdsbuf);	ao_unlock();}static void dsound_resume(void){	ao_lock();	IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);	ao_unlock();}static void UninitDirectSound(void){	if (hds)	{		IDirectSound_Release(hds);		hds = NULL;	}	if (hdsound_dll)	{		FreeLibrary(hdsound_dll);		hdsound_dll = NULL;	}}static BOOL CALLBACK DirectSoundEnum(LPGUID guid,LPCSTR desc,LPCSTR module,LPVOID context){	int* device_index=context;	if (device_num==*device_index)	{		if (guid)			memcpy(&device,guid,sizeof(GUID));	}	(*device_index)++;	return TRUE;}static int InitDirectSound(void){	DSCAPS dscaps;	HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);	HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACKA, LPVOID);	int device_index=0;	hdsound_dll = LoadLibrary("DSOUND.DLL");	if (hdsound_dll == NULL)	{		av_log(NULL, AV_LOG_ERROR, "LoadLibrary DSOUND.DLL error\n");		return -1;	}	OurDirectSoundCreate = (void*)GetProcAddress(hdsound_dll, "DirectSoundCreate");	OurDirectSoundEnumerate = (void*)GetProcAddress(hdsound_dll, "DirectSoundEnumerateA");	if (OurDirectSoundCreate == NULL || OurDirectSoundEnumerate == NULL)	{		FreeLibrary(hdsound_dll);		av_log(NULL, AV_LOG_ERROR, "GetProcAddress error\n");		return -1;	}	OurDirectSoundEnumerate(DirectSoundEnum,&device_index);	if FAILED(OurDirectSoundCreate((device_num)?&device:NULL, &hds, NULL ))	{		FreeLibrary(hdsound_dll);		av_log(NULL, AV_LOG_ERROR, "Create Device error\n");		return -1;	}	if (IDirectSound_SetCooperativeLevel(hds, GetDesktopWindow(), DSSCL_EXCLUSIVE))	{		IDirectSound_Release(hds);		FreeLibrary(hdsound_dll);		av_log(NULL, AV_LOG_ERROR, "IDirectSound_SetCooperativeLevel error\n");		return -1;	}	memset(&dscaps, 0, sizeof(DSCAPS));	dscaps.dwSize = sizeof(DSCAPS);	IDirectSound_GetCaps(hds, &dscaps);	return 0;}static void DestroyBuffer(void){	if (hdsbuf)	{		IDirectSoundBuffer_Release(hdsbuf);		hdsbuf = NULL;	}	if (hdspribuf)	{		IDirectSoundBuffer_Release(hdspribuf);		hdspribuf = NULL;	}}static int write_buffer(unsigned char *data, int len){	HRESULT res;	LPVOID lpvPtr1;	DWORD dwBytes1;	LPVOID lpvPtr2;	DWORD dwBytes2;	res = IDirectSoundBuffer_Lock(hdsbuf,write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);	if (DSERR_BUFFERLOST == res)	{		IDirectSoundBuffer_Restore(hdsbuf);		res = IDirectSoundBuffer_Lock(hdsbuf,write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);	}	if ( SUCCEEDED(res) )	{		if ( NULL != lpvPtr1 )			memcpy(lpvPtr1,data,dwBytes1);		if ( NULL != lpvPtr2 )			memcpy( lpvPtr2,data+dwBytes1,dwBytes2 ) ;		write_offset += dwBytes1 + dwBytes2 ;		if ( write_offset >= buffer_size )			write_offset = dwBytes2 ;		res = IDirectSoundBuffer_Unlock(hdsbuf,lpvPtr1,dwBytes1,lpvPtr2,dwBytes2);		if ( SUCCEEDED(res) )		{			DWORD status;			IDirectSoundBuffer_GetStatus(hdsbuf, &status);			if (!(status & DSBSTATUS_PLAYING))				res = IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);			return dwBytes1 + dwBytes2 ;		}	}	return 0;}static int dsound_control(int cmd, void *arg){	int left, right;	DWORD volume;	switch (cmd)	{	case AO_GET_VOLUME:		IDirectSoundBuffer_GetVolume(hdsbuf, &volume);		left = right = pow(10.0, (float)(volume+10000) / 5000.0);		return left;	case AO_ADD_VOLUME:		IDirectSoundBuffer_GetVolume(hdsbuf, &volume);		left = right = pow(10.0, (float)(volume+10000) / 5000.0);		left = left + 5;		left = left > 100 ? 100 : left;		volume = (DWORD)(log10(left) * 5000.0) - 10000;		IDirectSoundBuffer_SetVolume(hdsbuf, volume);		av_log(NULL, AV_LOG_INFO, "Change Volume to %d \r", left);		break;	case AO_SUB_VOLUME:		IDirectSoundBuffer_GetVolume(hdsbuf, &volume);		left = right = pow(10.0, (float)(volume+10000) / 5000.0);		left = left - 5;		left = left < 0 ? 0 : left;		volume = (DWORD)(log10(left) * 5000.0) - 10000;		IDirectSoundBuffer_SetVolume(hdsbuf, volume);		av_log(NULL, AV_LOG_INFO, "Change Volume to %d \r", left);		break;	case AO_PAUSE:		dsound_pause();		break;	case AO_RESUME:		dsound_resume();		break;	default:		av_log(NULL, AV_LOG_INFO, "Dsound Not Support the CMD now!\n");		break;	}	return -1;}static int sample_size( int fmt ){	switch (fmt)	{	case SAMPLE_FMT_U8:		return 8;	case SAMPLE_FMT_S16:		return 16;	case SAMPLE_FMT_S24:		return 24;	case SAMPLE_FMT_S32:		return 32;	case SAMPLE_FMT_FLT:		return 64;	}	return 16;}static int dsound_init(void){	int srate = dlpctxp->sample_rate;	int channels = dlpctxp->channels;	int format = dlpctxp->sample_fmt;	int res, bits_per_sample, outburst, bytes_per_second;	WAVEFORMATEXTENSIBLE wformat;	DSBUFFERDESC dsbpridesc;	DSBUFFERDESC dsbdesc;	if ( InitDirectSound() < 0 )	{		av_log(NULL, AV_LOG_ERROR, "InitDirectSound error\n");		return -1;	}	bits_per_sample = sample_size(format);	bytes_per_second = channels * srate * bits_per_sample / 8;	//fill waveformatex	ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE));	wformat.Format.cbSize = 0;	wformat.Format.nChannels = channels;	wformat.Format.nSamplesPerSec  = srate;	wformat.Format.wFormatTag      = WAVE_FORMAT_PCM;	wformat.Format.wBitsPerSample  = bits_per_sample;	wformat.Format.nBlockAlign     = channels * bits_per_sample / 8 ;	// fill in primary sound buffer descriptor	memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC));	dsbpridesc.dwSize = sizeof(DSBUFFERDESC);	dsbpridesc.dwFlags = DSBCAPS_PRIMARYBUFFER;	dsbpridesc.dwBufferBytes = 0;	dsbpridesc.lpwfxFormat = NULL;	// fill in the secondary sound buffer (=stream buffer) descriptor	memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));	dsbdesc.dwSize = sizeof(DSBUFFERDESC);	dsbdesc.dwFlags =	    DSBCAPS_GETCURRENTPOSITION2   /** Better position accuracy */	    | DSBCAPS_GLOBALFOCUS         /** Allows background playing */	    | DSBCAPS_CTRLVOLUME;         /** volume control enabled */	wformat.Format.nAvgBytesPerSec = srate * wformat.Format.nBlockAlign;	dsbdesc.dwBufferBytes = bytes_per_second;	dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat;	buffer_size = dsbdesc.dwBufferBytes;	write_offset = 0;	min_free_space = wformat.Format.nBlockAlign;	outburst = wformat.Format.nBlockAlign * 512;	res = IDirectSound_CreateSoundBuffer( hds, &dsbpridesc, &hdspribuf, NULL );	if ( res != DS_OK )	{		UninitDirectSound();		av_log(NULL, AV_LOG_ERROR, "IDirectSound_CreateSoundBuffer error\n");		return -1;	}	res = IDirectSoundBuffer_SetFormat( hdspribuf, (WAVEFORMATEX *)&wformat );	if ( res != DS_OK )		av_log(NULL, AV_LOG_ERROR, "IDirectSoundBuffer_SetFormat\n");	res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);	if (res != DS_OK)	{		if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE)		{			dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;			res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);		}		if (res != DS_OK)		{			UninitDirectSound();			av_log(NULL, AV_LOG_ERROR, "IDirectSound_CreateSoundBuffer stream buffer error\n");			return -1;		}	}	ao_lock_init();	av_log(NULL, AV_LOG_INFO, "dsound: buffersize=%d, srate=%d, \	       bits_per_sample=%d, bytes_per_second=%d, outburst=%d\n",	       buffer_size, srate, bits_per_sample, bytes_per_second, outburst);	return 0;}static int dsound_uninit(void){	DWORD status;	ao_lock();	IDirectSoundBuffer_Play(hdsbuf, 0, 0, 0);	while ( !IDirectSoundBuffer_GetStatus(hdsbuf,&status) &&	        (status&DSBSTATUS_PLAYING) )		usleep( 20* 1000 );	DestroyBuffer();	UninitDirectSound();	ao_lock_free();	return 0;}static int dsound_getspace(void){	int space, ret;	DWORD play_offset;	ao_lock();	IDirectSoundBuffer_GetCurrentPosition( hdsbuf,&play_offset,NULL );	space = buffer_size - ( write_offset - play_offset );	if (space > buffer_size)		space -= buffer_size;	if (space < min_free_space)		ret = 0;	ret = space - min_free_space;	ao_unlock();	return ret;}static void dsound_play(AVSample *s){	uint8_t *data = s->data;	int len = s->size;	while ( dsound_getspace() < len ) /* must wait */		usleep(1000);	ao_lock();	write_buffer(data, len);	ao_unlock();}ao_t ao_dsound ={	.id = AO_ID_DSOUND,	.name = "dsound",	.ao_init = dsound_init,	.ao_uninit = dsound_uninit,	.ao_play = dsound_play,	.ao_getspace = dsound_getspace,	.ao_control = dsound_control,};#endif

⌨️ 快捷键说明

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