~ubuntu-branches/ubuntu/quantal/linphone/quantal

« back to all changes in this revision

Viewing changes to mediastreamer2/src/msfileplayer.c

  • Committer: Bazaar Package Importer
  • Author(s): Samuel Mimram
  • Date: 2006-11-15 10:34:50 UTC
  • mfrom: (1.2.1 upstream) (2.1.8 feisty)
  • Revision ID: james.westby@ubuntu.com-20061115103450-qgafwcks2lkhctlj
* New upstream release.
* Enable video support.
* Fix mismatched #endif in mscommon.h, closes: #398307.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
mediastreamer2 library - modular sound and video processing and streaming
 
3
Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
 
4
 
 
5
This program is free software; you can redistribute it and/or
 
6
modify it under the terms of the GNU General Public License
 
7
as published by the Free Software Foundation; either version 2
 
8
of the License, or (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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
18
*/
 
19
 
 
20
#include "mediastreamer2/msfileplayer.h"
 
21
#include "mediastreamer2/waveheader.h"
 
22
#include "mediastreamer2/msticker.h"
 
23
 
 
24
 
 
25
static int player_close(MSFilter *f, void *arg);
 
26
 
 
27
typedef enum {
 
28
        CLOSED,
 
29
        STARTED,
 
30
        STOPPED
 
31
} PlayerState;
 
32
 
 
33
struct _PlayerData{
 
34
        int fd;
 
35
        PlayerState state;
 
36
        int rate;
 
37
        int nchannels;
 
38
        int hsize;
 
39
        int loop_after;
 
40
        int pause_time;
 
41
        bool_t swap;
 
42
};
 
43
 
 
44
typedef struct _PlayerData PlayerData;
 
45
 
 
46
static void player_init(MSFilter *f){
 
47
        PlayerData *d=ms_new(PlayerData,1);
 
48
        d->fd=-1;
 
49
        d->state=CLOSED;
 
50
        d->swap=FALSE;
 
51
        d->rate=8000;
 
52
        d->nchannels=1;
 
53
        d->hsize=0;
 
54
        d->loop_after=-1; /*by default, don't loop*/
 
55
        d->pause_time=0;
 
56
        f->data=d;      
 
57
}
 
58
 
 
59
static int read_wav_header(PlayerData *d){
 
60
        wave_header_t wav;
 
61
        if (read(d->fd,&wav,sizeof(wav))!=sizeof(wav)){
 
62
                ms_warning("Could not read wav header");
 
63
                return -1;
 
64
        }
 
65
        if (0!=strncmp(wav.riff_chunk.riff, "RIFF", 4) || 0!=strncmp(wav.riff_chunk.wave, "WAVE", 4)){
 
66
                ms_warning("Wrong wav header: (default rate/channel -> %i:%i)", d->rate, d->nchannels);
 
67
                return -1;
 
68
        }
 
69
        d->rate=wave_header_get_rate(&wav);
 
70
        d->nchannels=wave_header_get_channel(&wav);
 
71
        d->hsize=sizeof(wav);
 
72
#ifdef WORDS_BIGENDIAN
 
73
        if (wave_header_get_bpsmpl(&wav)==wave_header_get_channel(&wav) * 2)
 
74
                d->swap=TRUE;
 
75
#endif
 
76
        return 0;
 
77
}
 
78
 
 
79
static int player_open(MSFilter *f, void *arg){
 
80
        PlayerData *d=(PlayerData*)f->data;
 
81
        int fd;
 
82
        const char *file=(const char*)arg;
 
83
 
 
84
        if (d->fd>=0){
 
85
                player_close(f,NULL);
 
86
        }
 
87
        if ((fd=open(file,O_RDONLY))==-1){
 
88
                ms_warning("Failed to open %s",file);
 
89
                return -1;
 
90
        }
 
91
        d->state=STOPPED;
 
92
        d->fd=fd;
 
93
        if (strstr(file,".wav")!=NULL) read_wav_header(d);
 
94
        ms_message("%s opened: rate=%i,channel=%i",file,d->rate,d->nchannels);
 
95
        return 0;
 
96
}
 
97
 
 
98
static int player_start(MSFilter *f, void *arg){
 
99
        PlayerData *d=(PlayerData*)f->data;
 
100
        if (d->state==STOPPED)
 
101
                d->state=STARTED;
 
102
        return 0;
 
103
}
 
104
 
 
105
static int player_stop(MSFilter *f, void *arg){
 
106
        PlayerData *d=(PlayerData*)f->data;
 
107
        ms_filter_lock(f);
 
108
        if (d->state==STARTED){
 
109
                d->state=STOPPED;
 
110
                lseek(d->fd,d->hsize,SEEK_SET);
 
111
        }
 
112
        ms_filter_unlock(f);
 
113
        return 0;
 
114
}
 
115
 
 
116
static int player_close(MSFilter *f, void *arg){
 
117
        PlayerData *d=(PlayerData*)f->data;
 
118
        player_stop(f,NULL);
 
119
        if (d->fd>=0)   close(d->fd);
 
120
        d->fd=-1;
 
121
        d->state=CLOSED;
 
122
        return 0;
 
123
}
 
124
 
 
125
static void player_uninit(MSFilter *f){
 
126
        PlayerData *d=(PlayerData*)f->data;
 
127
        if (d->fd>=0) player_close(f,NULL);
 
128
        ms_free(d);
 
129
}
 
130
 
 
131
static void swap_bytes(unsigned char *bytes, int len){
 
132
        int i;
 
133
        char tmp;
 
134
        for(i=0;i<len;i+=2){
 
135
                tmp=bytes[i];
 
136
                bytes[i]=bytes[i+1];
 
137
                bytes[i+1]=tmp;
 
138
        }
 
139
}
 
140
 
 
141
static void player_process(MSFilter *f){
 
142
        PlayerData *d=(PlayerData*)f->data;
 
143
        int bytes=2*(f->ticker->interval*d->rate*d->nchannels)/1000;
 
144
        ms_filter_lock(f);
 
145
        if (d->state==STARTED){
 
146
                int err;
 
147
                mblk_t *om=allocb(bytes,0);
 
148
                if (d->pause_time>0){
 
149
                        err=bytes;
 
150
                        memset(om->b_wptr,0,bytes);
 
151
                        d->pause_time-=f->ticker->interval;
 
152
                }else{
 
153
                        err=read(d->fd,om->b_wptr,bytes);
 
154
                        if (d->swap) swap_bytes(om->b_wptr,bytes);
 
155
                }
 
156
                if (err>=0){
 
157
                        if (err!=0){
 
158
                                om->b_wptr+=bytes;
 
159
                                ms_queue_put(f->outputs[0],om);
 
160
                        }else freemsg(om);
 
161
                        if (err<bytes){
 
162
                                ms_filter_notify_no_arg(f,MS_FILE_PLAYER_EOF);
 
163
                                if (d->loop_after>=0){
 
164
                                        lseek(d->fd,d->hsize,SEEK_SET);
 
165
                                        d->pause_time=d->loop_after;
 
166
                                }else d->state=STOPPED;
 
167
                        }
 
168
                }else{
 
169
                        ms_warning("Fail to read %i bytes: %s",bytes,strerror(errno));
 
170
                }
 
171
        }
 
172
        ms_filter_unlock(f);
 
173
}
 
174
 
 
175
static int player_get_sr(MSFilter *f, void*arg){
 
176
        PlayerData *d=(PlayerData*)f->data;
 
177
        *((int*)arg)=d->rate;
 
178
        return 0;
 
179
}
 
180
 
 
181
static int player_loop(MSFilter *f, void *arg){
 
182
        PlayerData *d=(PlayerData*)f->data;
 
183
        d->loop_after=*((int*)arg);
 
184
        return 0;
 
185
}
 
186
 
 
187
static int player_eof(MSFilter *f, void *arg){
 
188
        PlayerData *d=(PlayerData*)f->data;
 
189
        if (d->fd<0 && d->state==CLOSED)
 
190
                *((int*)arg) = TRUE; /* 1 */
 
191
        else
 
192
                *((int*)arg) = FALSE; /* 0 */
 
193
        return 0;
 
194
}
 
195
 
 
196
static int player_get_nch(MSFilter *f, void *arg){
 
197
        PlayerData *d=(PlayerData*)f->data;
 
198
        *((int*)arg)=d->nchannels;
 
199
        return 0;
 
200
}
 
201
 
 
202
static MSFilterMethod player_methods[]={
 
203
        {       MS_FILE_PLAYER_OPEN,    player_open     },
 
204
        {       MS_FILE_PLAYER_START,   player_start    },
 
205
        {       MS_FILE_PLAYER_STOP,    player_stop     },
 
206
        {       MS_FILE_PLAYER_CLOSE,   player_close    },
 
207
        {       MS_FILTER_GET_SAMPLE_RATE, player_get_sr},
 
208
        {       MS_FILTER_GET_NCHANNELS, player_get_nch },
 
209
        {       MS_FILE_PLAYER_LOOP,    player_loop     },
 
210
        {       MS_FILE_PLAYER_DONE,    player_eof      },
 
211
        {       0,                      NULL            }
 
212
};
 
213
 
 
214
#ifdef WIN32
 
215
 
 
216
MSFilterDesc ms_file_player_desc={
 
217
        MS_FILE_PLAYER_ID,
 
218
        "MSFilePlayer",
 
219
        "Raw files and wav reader",
 
220
        MS_FILTER_OTHER,
 
221
        NULL,
 
222
    0,
 
223
        1,
 
224
        player_init,
 
225
        NULL,
 
226
    player_process,
 
227
        NULL,
 
228
    player_uninit,
 
229
        player_methods
 
230
};
 
231
 
 
232
#else
 
233
 
 
234
MSFilterDesc ms_file_player_desc={
 
235
        .id=MS_FILE_PLAYER_ID,
 
236
        .name="MSFilePlayer",
 
237
        .text="Raw files and wav reader",
 
238
        .category=MS_FILTER_OTHER,
 
239
        .ninputs=0,
 
240
        .noutputs=1,
 
241
        .init=player_init,
 
242
        .process=player_process,
 
243
        .uninit=player_uninit,
 
244
        .methods=player_methods
 
245
};
 
246
 
 
247
#endif
 
248
 
 
249
MS_FILTER_DESC_EXPORT(ms_file_player_desc)