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

📄 ao_win32.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
字号:
/****************************************************************************** * ao_win32.c: Windows waveOut interface for MPlayer * Copyright (c) 2002 - 2004 Sascha Sommer <saschasommer@freenet.de>. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. * *****************************************************************************/#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <mmsystem.h>#include "config.h"#include "libaf/af_format.h"#include "audio_out.h"#include "audio_out_internal.h"#include "mp_msg.h"//#include "libvo/fastmemcpy.h"#include "osdep/timer.h"#define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092#define WAVE_FORMAT_EXTENSIBLE      0xFFFEstatic const  GUID KSDATAFORMAT_SUBTYPE_PCM = {	0x1,0x0000,0x0010,{0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}};typedef struct {  WAVEFORMATEX  Format;  union {    WORD  wValidBitsPerSample;    WORD  wSamplesPerBlock;    WORD  wReserved;  } Samples;  DWORD  dwChannelMask;  GUID  SubFormat;} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;#define SPEAKER_FRONT_LEFT              0x1#define SPEAKER_FRONT_RIGHT             0x2#define SPEAKER_FRONT_CENTER            0x4#define SPEAKER_LOW_FREQUENCY           0x8#define SPEAKER_BACK_LEFT               0x10#define SPEAKER_BACK_RIGHT              0x20#define SPEAKER_FRONT_LEFT_OF_CENTER    0x40#define SPEAKER_FRONT_RIGHT_OF_CENTER   0x80#define SPEAKER_BACK_CENTER             0x100#define SPEAKER_SIDE_LEFT               0x200#define SPEAKER_SIDE_RIGHT              0x400#define SPEAKER_TOP_CENTER              0x800#define SPEAKER_TOP_FRONT_LEFT          0x1000#define SPEAKER_TOP_FRONT_CENTER        0x2000#define SPEAKER_TOP_FRONT_RIGHT         0x4000#define SPEAKER_TOP_BACK_LEFT           0x8000#define SPEAKER_TOP_BACK_CENTER         0x10000#define SPEAKER_TOP_BACK_RIGHT          0x20000static const int channel_mask[] = {  SPEAKER_FRONT_LEFT   | SPEAKER_FRONT_RIGHT  | SPEAKER_LOW_FREQUENCY,  SPEAKER_FRONT_LEFT   | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT  | SPEAKER_LOW_FREQUENCY,  SPEAKER_FRONT_LEFT   | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT  | SPEAKER_BACK_CENTER  | SPEAKER_LOW_FREQUENCY,  SPEAKER_FRONT_LEFT   | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT  | SPEAKER_BACK_LEFT    | SPEAKER_BACK_RIGHT     | SPEAKER_LOW_FREQUENCY};#define SAMPLESIZE   1024#define BUFFER_SIZE  4096#define BUFFER_COUNT 16static WAVEHDR*     waveBlocks;         //pointer to our ringbuffer memorystatic HWAVEOUT     hWaveOut;           //handle to the waveout devicestatic unsigned int buf_write=0;static unsigned int buf_write_pos=0;static int          full_buffers=0;static int          buffered_bytes=0;static ao_info_t info = {	"Windows waveOut audio output",	"win32",	"Sascha Sommer <saschasommer@freenet.de>",	""};LIBAO_EXTERN(win32)static void CALLBACK waveOutProc(HWAVEOUT hWaveOut,UINT uMsg,DWORD dwInstance,      DWORD dwParam1,DWORD dwParam2){	if(uMsg != WOM_DONE)        return;	if (full_buffers) {		buffered_bytes-=BUFFER_SIZE;		--full_buffers;	} else {		buffered_bytes=0;	}}// to set/get/query special features/parametersstatic int control(int cmd,void *arg){	DWORD volume;	switch (cmd)	{		case AOCONTROL_GET_VOLUME:		{			ao_control_vol_t* vol = (ao_control_vol_t*)arg;			waveOutGetVolume(hWaveOut,&volume);			vol->left = (float)(LOWORD(volume)/655.35);			vol->right = (float)(HIWORD(volume)/655.35);			mp_msg(MSGT_AO, MSGL_DBG2,"ao_win32: volume left:%f volume right:%f\n",vol->left,vol->right);			return CONTROL_OK;		}		case AOCONTROL_SET_VOLUME:		{			ao_control_vol_t* vol = (ao_control_vol_t*)arg;			volume = MAKELONG(vol->left*655.35,vol->right*655.35);			waveOutSetVolume(hWaveOut,volume);			return CONTROL_OK;		}	}    return -1;}// open & setup audio device// return: 1=success 0=failstatic int init(int rate,int channels,int format,int flags){	WAVEFORMATEXTENSIBLE wformat;      	DWORD totalBufferSize = (BUFFER_SIZE + sizeof(WAVEHDR)) * BUFFER_COUNT;	MMRESULT result;	unsigned char* buffer;	int i;   	switch(format){		case AF_FORMAT_AC3:		case AF_FORMAT_S24_LE:		case AF_FORMAT_S16_LE:		case AF_FORMAT_S8:			break;		default:			mp_msg(MSGT_AO, MSGL_V,"ao_win32: format %s not supported defaulting to Signed 16-bit Little-Endian\n",af_fmt2str_short(format));			format=AF_FORMAT_S16_LE;	}   	//fill global ao_data 	ao_data.channels=channels;	ao_data.samplerate=rate;	ao_data.format=format;	ao_data.bps=channels*rate;	if(format != AF_FORMAT_U8 && format != AF_FORMAT_S8)	  ao_data.bps*=2;	if(ao_data.buffersize==-1)	{		ao_data.buffersize=af_fmt2bits(format)/8;        ao_data.buffersize*= channels;		ao_data.buffersize*= SAMPLESIZE;	}	mp_msg(MSGT_AO, MSGL_V,"ao_win32: Samplerate:%iHz Channels:%i Format:%s\n",rate, channels, af_fmt2str_short(format));    mp_msg(MSGT_AO, MSGL_V,"ao_win32: Buffersize:%d\n",ao_data.buffersize);		//fill waveformatex    ZeroMemory( &wformat, sizeof(WAVEFORMATEXTENSIBLE));    wformat.Format.cbSize          = (channels>2)?sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX):0;    wformat.Format.nChannels       = channels;                    wformat.Format.nSamplesPerSec  = rate;                if(format == AF_FORMAT_AC3)    {        wformat.Format.wFormatTag      = WAVE_FORMAT_DOLBY_AC3_SPDIF;        wformat.Format.wBitsPerSample  = 16;        wformat.Format.nBlockAlign     = 4;    }    else     {        wformat.Format.wFormatTag      = (channels>2)?WAVE_FORMAT_EXTENSIBLE:WAVE_FORMAT_PCM;        wformat.Format.wBitsPerSample  = af_fmt2bits(format);         wformat.Format.nBlockAlign     = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3);    }	if(channels>2)	{        wformat.dwChannelMask = channel_mask[channels-3];        wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;	    wformat.Samples.wValidBitsPerSample=af_fmt2bits(format);    }      wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign; 	    //open sound device    //WAVE_MAPPER always points to the default wave device on the system    result = waveOutOpen(&hWaveOut,WAVE_MAPPER,(WAVEFORMATEX*)&wformat,(DWORD_PTR)waveOutProc,0,CALLBACK_FUNCTION);	if(result == WAVERR_BADFORMAT)	{		mp_msg(MSGT_AO, MSGL_ERR,"ao_win32: format not supported switching to default\n");        ao_data.channels = wformat.Format.nChannels = 2;	    ao_data.samplerate = wformat.Format.nSamplesPerSec = 44100;	    ao_data.format = AF_FORMAT_S16_LE;		ao_data.bps=ao_data.channels * ao_data.samplerate*2;	    wformat.Format.wBitsPerSample=16;        wformat.Format.wFormatTag=WAVE_FORMAT_PCM;		wformat.Format.nBlockAlign     = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3);        wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign;		ao_data.buffersize=(wformat.Format.wBitsPerSample>>3)*wformat.Format.nChannels*SAMPLESIZE;        result = waveOutOpen(&hWaveOut,WAVE_MAPPER,(WAVEFORMATEX*)&wformat,(DWORD_PTR)waveOutProc,0,CALLBACK_FUNCTION);	}	if(result != MMSYSERR_NOERROR)	{		mp_msg(MSGT_AO, MSGL_ERR,"ao_win32: unable to open wave mapper device (result=%i)\n",result);		return 0;    }	//allocate buffer memory as one big block	buffer = malloc(totalBufferSize);	memset(buffer,0x0,totalBufferSize);    //and setup pointers to each buffer     waveBlocks = (WAVEHDR*)buffer;    buffer += sizeof(WAVEHDR) * BUFFER_COUNT;    for(i = 0; i < BUFFER_COUNT; i++) {        waveBlocks[i].lpData = buffer;        buffer += BUFFER_SIZE;    }    buf_write=0;    buf_write_pos=0;    full_buffers=0;    buffered_bytes=0;    return 1;}// close audio devicestatic void uninit(int immed){    if(!immed)while(buffered_bytes > 0)usec_sleep(50000);    else buffered_bytes=0;	waveOutReset(hWaveOut);	waveOutClose(hWaveOut);	mp_msg(MSGT_AO, MSGL_V,"waveOut device closed\n");    free(waveBlocks);	mp_msg(MSGT_AO, MSGL_V,"buffer memory freed\n");}// stop playing and empty buffers (for seeking/pause)static void reset(){   	waveOutReset(hWaveOut);	buf_write=0;    buf_write_pos=0;	full_buffers=0;	buffered_bytes=0;}// stop playing, keep buffers (for pause)static void audio_pause(){    waveOutPause(hWaveOut);}// resume playing, after audio_pause()static void audio_resume(){	waveOutRestart(hWaveOut);}// return: how many bytes can be played without blockingstatic int get_space(){    return BUFFER_COUNT*BUFFER_SIZE - buffered_bytes;}//writes data into buffer, based on ringbuffer code in ao_sdl.cstatic int write_waveOutBuffer(unsigned char* data,int len){  WAVEHDR* current;  int len2=0;  int x;  while(len>0){                           current = &waveBlocks[buf_write];    if(buffered_bytes==BUFFER_COUNT*BUFFER_SIZE) break;    //unprepare the header if it is prepared	if(current->dwFlags & WHDR_PREPARED)            waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR));	x=BUFFER_SIZE-buf_write_pos;              if(x>len) x=len;                       memcpy(current->lpData+buf_write_pos,data+len2,x);     if(buf_write_pos==0)full_buffers++;    len2+=x; len-=x;                 	buffered_bytes+=x; buf_write_pos+=x; 	//prepare header and write data to device	current->dwBufferLength = buf_write_pos;	waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR));	waveOutWrite(hWaveOut, current, sizeof(WAVEHDR));    	if(buf_write_pos>=BUFFER_SIZE){        //buffer is full find next       // block is full, find next!       buf_write=(buf_write+1)%BUFFER_COUNT;  	   buf_write_pos=0;                     }                                   }  return len2;}// plays 'len' bytes of 'data'// it should round it down to outburst*n// return: number of bytes playedstatic int play(void* data,int len,int flags){	len = (len/ao_data.outburst)*ao_data.outburst;	return write_waveOutBuffer(data,len);}// return: delay in seconds between first and last sample in bufferstatic float get_delay(){	return (float)(buffered_bytes + ao_data.buffersize)/(float)ao_data.bps;}

⌨️ 快捷键说明

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