~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjmedia/src/pjmedia/mem_player.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: mem_player.c 3664 2011-07-19 03:42:28Z nanang $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
19
 */
 
20
#include <pjmedia/mem_port.h>
 
21
#include <pj/assert.h>
 
22
#include <pj/errno.h>
 
23
#include <pj/pool.h>
 
24
 
 
25
 
 
26
#define THIS_FILE           "mem_player.c"
 
27
 
 
28
#define SIGNATURE           PJMEDIA_SIG_PORT_MEM_PLAYER
 
29
#define BYTES_PER_SAMPLE    2
 
30
 
 
31
struct mem_player
 
32
{
 
33
    pjmedia_port     base;
 
34
 
 
35
    unsigned         options;
 
36
    pj_timestamp     timestamp;
 
37
 
 
38
    char            *buffer;
 
39
    pj_size_t        buf_size;
 
40
    char            *read_pos;
 
41
 
 
42
    pj_bool_t        eof;
 
43
    void            *user_data;
 
44
    pj_status_t    (*cb)(pjmedia_port *port,
 
45
                         void *user_data);
 
46
 
 
47
};
 
48
 
 
49
 
 
50
static pj_status_t mem_put_frame(pjmedia_port *this_port, 
 
51
                                 pjmedia_frame *frame);
 
52
static pj_status_t mem_get_frame(pjmedia_port *this_port, 
 
53
                                  pjmedia_frame *frame);
 
54
static pj_status_t mem_on_destroy(pjmedia_port *this_port);
 
55
 
 
56
 
 
57
PJ_DEF(pj_status_t) pjmedia_mem_player_create( pj_pool_t *pool,
 
58
                                               const void *buffer,
 
59
                                               pj_size_t size,
 
60
                                               unsigned clock_rate,
 
61
                                               unsigned channel_count,
 
62
                                               unsigned samples_per_frame,
 
63
                                               unsigned bits_per_sample,
 
64
                                               unsigned options,
 
65
                                               pjmedia_port **p_port )
 
66
{
 
67
    struct mem_player *port;
 
68
    pj_str_t name = pj_str("memplayer");
 
69
 
 
70
    /* Sanity check */
 
71
    PJ_ASSERT_RETURN(pool && buffer && size && clock_rate && channel_count &&
 
72
                     samples_per_frame && bits_per_sample && p_port,
 
73
                     PJ_EINVAL);
 
74
 
 
75
    /* Can only support 16bit PCM */
 
76
    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);
 
77
 
 
78
 
 
79
    port = PJ_POOL_ZALLOC_T(pool, struct mem_player);
 
80
    PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM);
 
81
 
 
82
    /* Create the port */
 
83
    pjmedia_port_info_init(&port->base.info, &name, SIGNATURE, clock_rate,
 
84
                           channel_count, bits_per_sample, samples_per_frame);
 
85
 
 
86
    port->base.put_frame = &mem_put_frame;
 
87
    port->base.get_frame = &mem_get_frame;
 
88
    port->base.on_destroy = &mem_on_destroy;
 
89
 
 
90
 
 
91
    /* Save the buffer */
 
92
    port->buffer = port->read_pos = (char*)buffer;
 
93
    port->buf_size = size;
 
94
 
 
95
    /* Options */
 
96
    port->options = options;
 
97
 
 
98
    *p_port = &port->base;
 
99
 
 
100
    return PJ_SUCCESS;
 
101
}
 
102
 
 
103
 
 
104
 
 
105
/*
 
106
 * Register a callback to be called when the file reading has reached the
 
107
 * end of buffer.
 
108
 */
 
109
PJ_DEF(pj_status_t) pjmedia_mem_player_set_eof_cb( pjmedia_port *port,
 
110
                               void *user_data,
 
111
                               pj_status_t (*cb)(pjmedia_port *port,
 
112
                                                 void *usr_data))
 
113
{
 
114
    struct mem_player *player;
 
115
 
 
116
    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE,
 
117
                     PJ_EINVALIDOP);
 
118
 
 
119
    player = (struct mem_player*) port;
 
120
    player->user_data = user_data;
 
121
    player->cb = cb;
 
122
 
 
123
    return PJ_SUCCESS;
 
124
}
 
125
 
 
126
 
 
127
static pj_status_t mem_put_frame( pjmedia_port *this_port, 
 
128
                                  pjmedia_frame *frame)
 
129
{
 
130
    PJ_UNUSED_ARG(this_port);
 
131
    PJ_UNUSED_ARG(frame);
 
132
 
 
133
    return PJ_SUCCESS;
 
134
}
 
135
 
 
136
 
 
137
static pj_status_t mem_get_frame( pjmedia_port *this_port, 
 
138
                                  pjmedia_frame *frame)
 
139
{
 
140
    struct mem_player *player;
 
141
    char *endpos;
 
142
    pj_size_t size_needed, size_written;
 
143
 
 
144
    PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE,
 
145
                     PJ_EINVALIDOP);
 
146
 
 
147
    player = (struct mem_player*) this_port;
 
148
 
 
149
    if (player->eof) {
 
150
        pj_status_t status = PJ_SUCCESS;
 
151
 
 
152
        /* Call callback, if any */
 
153
        if (player->cb)
 
154
            status = (*player->cb)(this_port, player->user_data);
 
155
 
 
156
        /* If callback returns non PJ_SUCCESS or 'no loop' is specified
 
157
         * return immediately (and don't try to access player port since
 
158
         * it might have been destroyed by the callback).
 
159
         */
 
160
        if ((status != PJ_SUCCESS) || (player->options & PJMEDIA_MEM_NO_LOOP)) {
 
161
            frame->type = PJMEDIA_FRAME_TYPE_NONE;
 
162
            return PJ_EEOF;
 
163
        }
 
164
        
 
165
        player->eof = PJ_FALSE;
 
166
    }
 
167
 
 
168
    size_needed = PJMEDIA_PIA_AVG_FSZ(&this_port->info);
 
169
    size_written = 0;
 
170
    endpos = player->buffer + player->buf_size;
 
171
 
 
172
    while (size_written < size_needed) {
 
173
        char *dst = ((char*)frame->buf) + size_written;
 
174
        pj_size_t max;
 
175
        
 
176
        max = size_needed - size_written;
 
177
        if (endpos - player->read_pos < (int)max)
 
178
            max = endpos - player->read_pos;
 
179
 
 
180
        pj_memcpy(dst, player->read_pos, max);
 
181
        size_written += max;
 
182
        player->read_pos += max;
 
183
 
 
184
        pj_assert(player->read_pos <= endpos);
 
185
 
 
186
        if (player->read_pos == endpos) {
 
187
            /* Set EOF flag */
 
188
            player->eof = PJ_TRUE;
 
189
            /* Reset read pointer */
 
190
            player->read_pos = player->buffer;
 
191
 
 
192
            /* Pad with zeroes then return for no looped play */
 
193
            if (player->options & PJMEDIA_MEM_NO_LOOP) {
 
194
                pj_size_t null_len;
 
195
 
 
196
                null_len = size_needed - size_written;
 
197
                pj_bzero(dst + max, null_len);
 
198
                break;
 
199
            }
 
200
        }
 
201
    }
 
202
 
 
203
    frame->size = PJMEDIA_PIA_AVG_FSZ(&this_port->info);
 
204
    frame->timestamp.u64 = player->timestamp.u64;
 
205
    frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
 
206
 
 
207
    player->timestamp.u64 += PJMEDIA_PIA_SPF(&this_port->info);
 
208
 
 
209
    return PJ_SUCCESS;
 
210
}
 
211
 
 
212
 
 
213
static pj_status_t mem_on_destroy(pjmedia_port *this_port)
 
214
{
 
215
    PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE,
 
216
                     PJ_EINVALIDOP);
 
217
 
 
218
    /* Destroy signature */
 
219
    this_port->info.signature = 0;
 
220
 
 
221
    return PJ_SUCCESS;
 
222
}
 
223
 
 
224