~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-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 */