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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjmedia/src/pjmedia-codec/h263_packetizer.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: h263_packetizer.c 4006 2012-04-02 08:40:54Z nanang $ */
2
 
/*
3
 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 2 of the License, or
8
 
 * (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
 
#include <pjmedia-codec/h263_packetizer.h>
20
 
#include <pjmedia/types.h>
21
 
#include <pj/assert.h>
22
 
#include <pj/errno.h>
23
 
#include <pj/string.h>
24
 
 
25
 
 
26
 
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
27
 
 
28
 
 
29
 
#define THIS_FILE       "h263_packetizer.c"
30
 
 
31
 
 
32
 
/* H.263 packetizer definition */
33
 
struct pjmedia_h263_packetizer {
34
 
    /* Current settings */
35
 
    pjmedia_h263_packetizer_cfg cfg;
36
 
 
37
 
    /* Unpacketizer state */
38
 
    unsigned        unpack_last_sync_pos;
39
 
    pj_bool_t       unpack_prev_lost;
40
 
};
41
 
 
42
 
 
43
 
/*
44
 
 * Find synchronization point (PSC, slice, GSBC, EOS, EOSBS) in H.263
45
 
 * bitstream.
46
 
 */
47
 
static pj_uint8_t* find_sync_point(pj_uint8_t *data,
48
 
                                   pj_size_t data_len)
49
 
{
50
 
    pj_uint8_t *p = data, *end = data+data_len-1;
51
 
 
52
 
    while (p < end && (*p || *(p+1)))
53
 
        ++p;
54
 
 
55
 
    if (p == end)
56
 
        return NULL;
57
 
 
58
 
    return p;
59
 
}
60
 
 
61
 
 
62
 
/*
63
 
 * Find synchronization point (PSC, slice, GSBC, EOS, EOSBS) in H.263
64
 
 * bitstream, in reversed manner.
65
 
 */
66
 
static pj_uint8_t* find_sync_point_rev(pj_uint8_t *data,
67
 
                                       pj_size_t data_len)
68
 
{
69
 
    pj_uint8_t *p = data+data_len-2;
70
 
 
71
 
    while (p >= data && (*p || *(p+1)))
72
 
        --p;
73
 
 
74
 
    if (p < data)
75
 
        return (data + data_len);
76
 
 
77
 
    return p;
78
 
}
79
 
 
80
 
 
81
 
/*
82
 
 * Create H263 packetizer.
83
 
 */
84
 
PJ_DEF(pj_status_t) pjmedia_h263_packetizer_create(
85
 
                                pj_pool_t *pool,
86
 
                                const pjmedia_h263_packetizer_cfg *cfg,
87
 
                                pjmedia_h263_packetizer **p)
88
 
{
89
 
    pjmedia_h263_packetizer *p_;
90
 
 
91
 
    PJ_ASSERT_RETURN(pool && p, PJ_EINVAL);
92
 
 
93
 
    if (cfg && cfg->mode != PJMEDIA_H263_PACKETIZER_MODE_RFC4629)
94
 
        return PJ_ENOTSUP;
95
 
 
96
 
    p_ = PJ_POOL_ZALLOC_T(pool, pjmedia_h263_packetizer);
97
 
    if (cfg) {
98
 
        pj_memcpy(&p_->cfg, cfg, sizeof(*cfg));
99
 
    } else {
100
 
        p_->cfg.mode = PJMEDIA_H263_PACKETIZER_MODE_RFC4629;
101
 
        p_->cfg.mtu = PJMEDIA_MAX_VID_PAYLOAD_SIZE;
102
 
    }
103
 
 
104
 
    *p = p_;
105
 
 
106
 
    return PJ_SUCCESS;
107
 
}
108
 
 
109
 
 
110
 
/*
111
 
 * Generate an RTP payload from H.263 frame bitstream, in-place processing.
112
 
 */
113
 
PJ_DEF(pj_status_t) pjmedia_h263_packetize(pjmedia_h263_packetizer *pktz,
114
 
                                           pj_uint8_t *bits,
115
 
                                           pj_size_t bits_len,
116
 
                                           unsigned *pos,
117
 
                                           const pj_uint8_t **payload,
118
 
                                           pj_size_t *payload_len)
119
 
{
120
 
    pj_uint8_t *p, *end;
121
 
 
122
 
    pj_assert(pktz && bits && pos && payload && payload_len);
123
 
    pj_assert(*pos <= bits_len);
124
 
 
125
 
    p = bits + *pos;
126
 
    end = bits + bits_len;
127
 
 
128
 
    /* Put two octets payload header */
129
 
    if ((end-p > 2) && *p==0 && *(p+1)==0) {
130
 
        /* The bitstream starts with synchronization point, just override
131
 
         * the two zero octets (sync point mark) for payload header.
132
 
         */
133
 
        *p = 0x04;
134
 
    } else {
135
 
        /* Not started in synchronization point, we will use two octets
136
 
         * preceeding the bitstream for payload header!
137
 
         */
138
 
 
139
 
        if (*pos < 2) {
140
 
            /* Invalid H263 bitstream, it's not started with PSC */
141
 
            return PJ_EINVAL;
142
 
        }
143
 
 
144
 
        p -= 2;
145
 
        *p = 0;
146
 
    }
147
 
    *(p+1) = 0;
148
 
 
149
 
    /* When bitstream truncation needed because of payload length/MTU
150
 
     * limitation, try to use sync point for the payload boundary.
151
 
     */
152
 
    if (end-p > pktz->cfg.mtu) {
153
 
        end = find_sync_point_rev(p+2, pktz->cfg.mtu-2);
154
 
    }
155
 
 
156
 
    *payload = p;
157
 
    *payload_len = end-p;
158
 
    *pos = end - bits;
159
 
 
160
 
    return PJ_SUCCESS;
161
 
}
162
 
 
163
 
 
164
 
/*
165
 
 * Append an RTP payload to a H.263 picture bitstream.
166
 
 */
167
 
PJ_DEF(pj_status_t) pjmedia_h263_unpacketize (pjmedia_h263_packetizer *pktz,
168
 
                                              const pj_uint8_t *payload,
169
 
                                              pj_size_t payload_len,
170
 
                                              pj_uint8_t *bits,
171
 
                                              pj_size_t bits_size,
172
 
                                              unsigned *pos)
173
 
{
174
 
    pj_uint8_t P, V, PLEN;
175
 
    const pj_uint8_t *p = payload;
176
 
    pj_uint8_t *q;
177
 
 
178
 
    q = bits + *pos;
179
 
 
180
 
    /* Check if this is a missing/lost packet */
181
 
    if (payload == NULL) {
182
 
        pktz->unpack_prev_lost = PJ_TRUE;
183
 
        return PJ_SUCCESS;
184
 
    }
185
 
 
186
 
    /* H263 payload header size is two octets */
187
 
    if (payload_len < 2) {
188
 
        /* Invalid bitstream, discard this payload */
189
 
        pktz->unpack_prev_lost = PJ_TRUE;
190
 
        return PJ_EINVAL;
191
 
    }
192
 
 
193
 
    /* Reset last sync point for every new picture bitstream */
194
 
    if (*pos == 0)
195
 
        pktz->unpack_last_sync_pos = 0;
196
 
 
197
 
    /* Get payload header info */
198
 
    P = *p & 0x04;
199
 
    V = *p & 0x02;
200
 
    PLEN = ((*p & 0x01) << 5) + ((*(p+1) & 0xF8)>>3);
201
 
 
202
 
    /* Get start bitstream pointer */
203
 
    p += 2;         /* Skip payload header */
204
 
    if (V)
205
 
        p += 1;     /* Skip VRC data */
206
 
    if (PLEN)
207
 
        p += PLEN;  /* Skip extra picture header data */
208
 
 
209
 
    /* Get bitstream length */
210
 
    if (payload_len > (pj_size_t)(p - payload)) {
211
 
        payload_len -= (p - payload);
212
 
    } else {
213
 
        /* Invalid bitstream, discard this payload */
214
 
        pktz->unpack_prev_lost = PJ_TRUE;
215
 
        return PJ_EINVAL;
216
 
    }
217
 
 
218
 
    /* Validate bitstream length */
219
 
    if (bits_size < *pos + payload_len + 2) {
220
 
        /* Insufficient bistream buffer, discard this payload */
221
 
        pj_assert(!"Insufficient H.263 bitstream buffer");
222
 
        pktz->unpack_prev_lost = PJ_TRUE;
223
 
        return PJ_ETOOSMALL;
224
 
    }
225
 
 
226
 
    /* Start writing bitstream */
227
 
 
228
 
    /* No sync point flag */
229
 
    if (!P) {
230
 
        if (*pos == 0) {
231
 
            /* Previous packet must be lost */
232
 
            pktz->unpack_prev_lost = PJ_TRUE;
233
 
 
234
 
            /* If there is extra picture header, let's use it. */
235
 
            if (PLEN) {
236
 
                /* Write two zero octets for PSC */
237
 
                *q++ = 0;
238
 
                *q++ = 0;
239
 
                /* Copy the picture header */
240
 
                p -= PLEN;
241
 
                pj_memcpy(q, p, PLEN);
242
 
                p += PLEN;
243
 
                q += PLEN;
244
 
            }
245
 
        } else if (pktz->unpack_prev_lost) {
246
 
            /* If prev packet was lost, revert the bitstream pointer to
247
 
             * the last sync point.
248
 
             */
249
 
            pj_assert(pktz->unpack_last_sync_pos <= *pos);
250
 
            q = bits + pktz->unpack_last_sync_pos;
251
 
        }
252
 
 
253
 
        /* There was packet lost, see if this payload contain sync point
254
 
         * (usable data).
255
 
         */
256
 
        if (pktz->unpack_prev_lost) {
257
 
            pj_uint8_t *sync;
258
 
            sync = find_sync_point((pj_uint8_t*)p, payload_len);
259
 
            if (sync) {
260
 
                /* Got sync point, update P/sync-point flag */
261
 
                P = 1;
262
 
                /* Skip the two zero octets */
263
 
                sync += 2;
264
 
                /* Update payload length and start bitstream pointer */
265
 
                payload_len -= (sync - p);
266
 
                p = sync;
267
 
            } else {
268
 
                /* No sync point in it, just discard this payload */
269
 
                return PJ_EIGNORED;
270
 
            }
271
 
        }
272
 
    }
273
 
 
274
 
    /* Write two zero octets when payload flagged with sync point */
275
 
    if (P) {
276
 
        pktz->unpack_last_sync_pos = q - bits;
277
 
        *q++ = 0;
278
 
        *q++ = 0;
279
 
    }
280
 
 
281
 
    /* Write the payload to the bitstream */
282
 
    pj_memcpy(q, p, payload_len);
283
 
    q += payload_len;
284
 
 
285
 
    /* Update the bitstream writing offset */
286
 
    *pos = q - bits;
287
 
 
288
 
    pktz->unpack_prev_lost = PJ_FALSE;
289
 
 
290
 
    return PJ_SUCCESS;
291
 
}
292
 
 
293
 
 
294
 
#endif /* PJMEDIA_HAS_VIDEO */