📄 msfileplayer.c
字号:
/*mediastreamer2 library - modular sound and video processing and streamingCopyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include "mediastreamer2/msfileplayer.h"#include "mediastreamer2/waveheader.h"#include "mediastreamer2/msticker.h"static int player_close(MSFilter *f, void *arg);typedef enum { CLOSED, STARTED, STOPPED} PlayerState;struct _PlayerData{ int fd; PlayerState state; int rate; int nchannels; int hsize; int loop_after; int pause_time; bool_t swap;};typedef struct _PlayerData PlayerData;static void player_init(MSFilter *f){ PlayerData *d=ms_new(PlayerData,1); d->fd=-1; d->state=CLOSED; d->swap=FALSE; d->rate=8000; d->nchannels=1; d->hsize=0; d->loop_after=-1; /*by default, don't loop*/ d->pause_time=0; f->data=d; }static int read_wav_header(PlayerData *d){ char header1[sizeof(riff_t)]; char header2[sizeof(format_t)]; char header3[sizeof(data_t)]; int count; riff_t *riff_chunk=(riff_t*)header1; format_t *format_chunk=(format_t*)header2; data_t *data_chunk=(data_t*)header3; unsigned long len=0; len = read(d->fd, header1, sizeof(header1)) ; if (len != sizeof(header1)){ ms_warning("Wrong wav header: cannot read file"); return -1; } if (0!=strncmp(riff_chunk->riff, "RIFF", 4) || 0!=strncmp(riff_chunk->wave, "WAVE", 4)){ ms_warning("Wrong wav header (not RIFF/WAV)"); return -1; } len = read(d->fd, header2, sizeof(header2)) ; if (len != sizeof(header2)){ ms_warning("Wrong wav header: cannot read file"); return -1; } d->rate=le_uint32(format_chunk->rate); d->nchannels=le_uint16(format_chunk->channel); if (format_chunk->len-0x10>0) { lseek(d->fd,(format_chunk->len-0x10),SEEK_CUR); } d->hsize=sizeof(wave_header_t)-0x10+format_chunk->len; len = read(d->fd, header3, sizeof(header3)) ; if (len != sizeof(header3)){ ms_warning("Wrong wav header: cannot read file"); return -1; } count=0; while (strncmp(data_chunk->data, "data", 4)!=0 && count<30) { ms_warning("skipping chunk=%s len=%i", data_chunk->data, data_chunk->len); lseek(d->fd,data_chunk->len,SEEK_CUR); count++; d->hsize=d->hsize+len+data_chunk->len; len = read(d->fd, header3, sizeof(header3)) ; if (len != sizeof(header3)){ ms_warning("Wrong wav header: cannot read file"); return -1; } }#ifdef WORDS_BIGENDIAN if (le_uint16(format_chunk->blockalign)==le_uint16(format_chunk->channel) * 2) d->swap=TRUE;#endif return 0;}static int player_open(MSFilter *f, void *arg){ PlayerData *d=(PlayerData*)f->data; int fd; const char *file=(const char*)arg; if (d->fd>=0){ player_close(f,NULL); } if ((fd=open(file,O_RDONLY))==-1){ ms_warning("Failed to open %s",file); return -1; } d->state=STOPPED; d->fd=fd; if (strstr(file,".wav")!=NULL) read_wav_header(d); ms_message("%s opened: rate=%i,channel=%i",file,d->rate,d->nchannels); return 0;}static int player_start(MSFilter *f, void *arg){ PlayerData *d=(PlayerData*)f->data; if (d->state==STOPPED) d->state=STARTED; return 0;}static int player_stop(MSFilter *f, void *arg){ PlayerData *d=(PlayerData*)f->data; ms_filter_lock(f); if (d->state==STARTED){ d->state=STOPPED; lseek(d->fd,d->hsize,SEEK_SET); } ms_filter_unlock(f); return 0;}static int player_close(MSFilter *f, void *arg){ PlayerData *d=(PlayerData*)f->data; player_stop(f,NULL); if (d->fd>=0) close(d->fd); d->fd=-1; d->state=CLOSED; return 0;}static void player_uninit(MSFilter *f){ PlayerData *d=(PlayerData*)f->data; if (d->fd>=0) player_close(f,NULL); ms_free(d);}static void swap_bytes(unsigned char *bytes, int len){ int i; unsigned char tmp; for(i=0;i<len;i+=2){ tmp=bytes[i]; bytes[i]=bytes[i+1]; bytes[i+1]=tmp; }}static void player_process(MSFilter *f){ PlayerData *d=(PlayerData*)f->data; int bytes=2*(f->ticker->interval*d->rate*d->nchannels)/1000; ms_filter_lock(f); if (d->state==STARTED){ int err; mblk_t *om=allocb(bytes,0); if (d->pause_time>0){ err=bytes; memset(om->b_wptr,0,bytes); d->pause_time-=f->ticker->interval; }else{ err=read(d->fd,om->b_wptr,bytes); if (d->swap) swap_bytes(om->b_wptr,bytes); } if (err>=0){ if (err!=0){ om->b_wptr+=bytes; ms_queue_put(f->outputs[0],om); }else freemsg(om); if (err<bytes){ ms_filter_notify_no_arg(f,MS_FILE_PLAYER_EOF); lseek(d->fd,d->hsize,SEEK_SET); /* special value for playing file only once */ if (d->loop_after==-2) { d->state=STOPPED; ms_filter_unlock(f); return; } if (d->loop_after>=0){ d->pause_time=d->loop_after; } } }else{ ms_warning("Fail to read %i bytes: %s",bytes,strerror(errno)); } } ms_filter_unlock(f);}static int player_get_sr(MSFilter *f, void*arg){ PlayerData *d=(PlayerData*)f->data; *((int*)arg)=d->rate; return 0;}static int player_loop(MSFilter *f, void *arg){ PlayerData *d=(PlayerData*)f->data; d->loop_after=*((int*)arg); return 0;}static int player_eof(MSFilter *f, void *arg){ PlayerData *d=(PlayerData*)f->data; if (d->fd<0 && d->state==CLOSED) *((int*)arg) = TRUE; /* 1 */ else *((int*)arg) = FALSE; /* 0 */ return 0;}static int player_get_nch(MSFilter *f, void *arg){ PlayerData *d=(PlayerData*)f->data; *((int*)arg)=d->nchannels; return 0;}static MSFilterMethod player_methods[]={ { MS_FILE_PLAYER_OPEN, player_open }, { MS_FILE_PLAYER_START, player_start }, { MS_FILE_PLAYER_STOP, player_stop }, { MS_FILE_PLAYER_CLOSE, player_close }, { MS_FILTER_GET_SAMPLE_RATE, player_get_sr}, { MS_FILTER_GET_NCHANNELS, player_get_nch }, { MS_FILE_PLAYER_LOOP, player_loop }, { MS_FILE_PLAYER_DONE, player_eof }, { 0, NULL }};#ifdef WIN32MSFilterDesc ms_file_player_desc={ MS_FILE_PLAYER_ID, "MSFilePlayer", "Raw files and wav reader", MS_FILTER_OTHER, NULL, 0, 1, player_init, NULL, player_process, NULL, player_uninit, player_methods};#elseMSFilterDesc ms_file_player_desc={ .id=MS_FILE_PLAYER_ID, .name="MSFilePlayer", .text="Raw files and wav reader", .category=MS_FILTER_OTHER, .ninputs=0, .noutputs=1, .init=player_init, .process=player_process, .uninit=player_uninit, .methods=player_methods};#endifMS_FILTER_DESC_EXPORT(ms_file_player_desc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -