~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/h264_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: h264_packetizer.c 4006 2012-04-02 08:40:54Z nanang $ */
 
2
/* 
 
3
 * Copyright (C) 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/h264_packetizer.h>
 
20
#include <pjmedia/types.h>
 
21
#include <pj/assert.h>
 
22
#include <pj/errno.h>
 
23
#include <pj/log.h>
 
24
#include <pj/pool.h>
 
25
#include <pj/string.h>
 
26
 
 
27
 
 
28
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
 
29
 
 
30
 
 
31
#define THIS_FILE               "h264_packetizer.c"
 
32
 
 
33
#define DBG_PACKETIZE           0
 
34
#define DBG_UNPACKETIZE         0
 
35
 
 
36
 
 
37
/* H.264 packetizer definition */
 
38
struct pjmedia_h264_packetizer
 
39
{
 
40
    /* Current settings */
 
41
    pjmedia_h264_packetizer_cfg cfg;
 
42
    
 
43
    /* Unpacketizer state */
 
44
    unsigned        unpack_last_sync_pos;
 
45
    pj_bool_t       unpack_prev_lost;
 
46
};
 
47
 
 
48
 
 
49
/* Enumeration of H.264 NAL unit types */
 
50
enum
 
51
{
 
52
    NAL_TYPE_SINGLE_NAL_MIN     = 1,
 
53
    NAL_TYPE_SINGLE_NAL_MAX     = 23,
 
54
    NAL_TYPE_STAP_A             = 24,
 
55
    NAL_TYPE_FU_A               = 28,
 
56
};
 
57
 
 
58
 
 
59
/*
 
60
 * Find next NAL unit from the specified H.264 bitstream data.
 
61
 */
 
62
static pj_uint8_t* find_next_nal_unit(pj_uint8_t *start,
 
63
                                      pj_uint8_t *end)
 
64
{
 
65
    pj_uint8_t *p = start;
 
66
 
 
67
    /* Simply lookup "0x000001" pattern */
 
68
    while (p <= end-3 && (p[0] || p[1] || p[2]!=1))
 
69
        ++p;
 
70
 
 
71
    if (p > end-3)
 
72
        /* No more NAL unit in this bitstream */
 
73
        return NULL;
 
74
 
 
75
    /* Include 8 bits leading zero */
 
76
    if (p>start && *(p-1)==0)
 
77
        return (p-1);
 
78
 
 
79
    return p;
 
80
}
 
81
 
 
82
 
 
83
/*
 
84
 * Create H264 packetizer.
 
85
 */
 
86
PJ_DEF(pj_status_t) pjmedia_h264_packetizer_create(
 
87
                                pj_pool_t *pool,
 
88
                                const pjmedia_h264_packetizer_cfg *cfg,
 
89
                                pjmedia_h264_packetizer **p)
 
90
{
 
91
    pjmedia_h264_packetizer *p_;
 
92
 
 
93
    PJ_ASSERT_RETURN(pool && p, PJ_EINVAL);
 
94
 
 
95
    if (cfg &&
 
96
        cfg->mode != PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED &&
 
97
        cfg->mode != PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL)
 
98
    {
 
99
        return PJ_ENOTSUP;
 
100
    }
 
101
 
 
102
    p_ = PJ_POOL_ZALLOC_T(pool, pjmedia_h264_packetizer);
 
103
    if (cfg) {
 
104
        pj_memcpy(&p_->cfg, cfg, sizeof(*cfg));
 
105
    } else {
 
106
        p_->cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED;
 
107
        p_->cfg.mtu = PJMEDIA_MAX_VID_PAYLOAD_SIZE;
 
108
    }
 
109
 
 
110
    *p = p_;
 
111
 
 
112
    return PJ_SUCCESS;
 
113
}
 
114
 
 
115
 
 
116
 
 
117
/*
 
118
 * Generate an RTP payload from H.264 frame bitstream, in-place processing.
 
119
 */
 
120
PJ_DEF(pj_status_t) pjmedia_h264_packetize(pjmedia_h264_packetizer *pktz,
 
121
                                           pj_uint8_t *buf,
 
122
                                           pj_size_t buf_len,
 
123
                                           unsigned *pos,
 
124
                                           const pj_uint8_t **payload,
 
125
                                           pj_size_t *payload_len)
 
126
{
 
127
    pj_uint8_t *nal_start = NULL, *nal_end = NULL, *nal_octet = NULL;
 
128
    pj_uint8_t *p, *end;
 
129
    enum { 
 
130
        HEADER_SIZE_FU_A             = 2,
 
131
        HEADER_SIZE_STAP_A           = 3,
 
132
    };
 
133
    enum { MAX_NALS_IN_AGGR = 32 };
 
134
 
 
135
#if DBG_PACKETIZE
 
136
    if (*pos == 0 && buf_len) {
 
137
        PJ_LOG(3, ("h264pack", "<< Start packing new frame >>"));
 
138
    }
 
139
#endif
 
140
 
 
141
    p = buf + *pos;
 
142
    end = buf + buf_len;
 
143
 
 
144
    /* Find NAL unit startcode */
 
145
    if (end-p >= 4)
 
146
        nal_start = find_next_nal_unit(p, p+4);
 
147
    if (nal_start) {
 
148
        /* Get NAL unit octet pointer */
 
149
        while (*nal_start++ == 0);
 
150
        nal_octet = nal_start;
 
151
    } else {
 
152
        /* This NAL unit is being fragmented */
 
153
        nal_start = p;
 
154
    }
 
155
 
 
156
    /* Get end of NAL unit */
 
157
    p = nal_start+pktz->cfg.mtu+1;
 
158
    if (p > end || pktz->cfg.mode==PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL) 
 
159
        p = end;
 
160
    nal_end = find_next_nal_unit(nal_start, p); 
 
161
    if (!nal_end)
 
162
        nal_end = p;
 
163
 
 
164
    /* Validate MTU vs NAL length on single NAL unit packetization */
 
165
    if ((pktz->cfg.mode==PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL) &&
 
166
        nal_end - nal_start > pktz->cfg.mtu)
 
167
    {
 
168
        //pj_assert(!"MTU too small for H.264 single NAL packetization mode");
 
169
        PJ_LOG(2,("h264_packetizer.c",
 
170
                  "MTU too small for H.264 (required=%u, MTU=%u)",
 
171
                  nal_end - nal_start, pktz->cfg.mtu));
 
172
        return PJ_ETOOSMALL;
 
173
    }
 
174
 
 
175
    /* Evaluate the proper payload format structure */
 
176
 
 
177
    /* Fragmentation (FU-A) packet */
 
178
    if ((pktz->cfg.mode != PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL) &&
 
179
        (!nal_octet || nal_end-nal_start > pktz->cfg.mtu))
 
180
    {
 
181
        pj_uint8_t NRI, TYPE;
 
182
 
 
183
        if (nal_octet) {
 
184
            /* We have NAL unit octet, so this is the first fragment */
 
185
            NRI = (*nal_octet & 0x60) >> 5;
 
186
            TYPE = *nal_octet & 0x1F;
 
187
 
 
188
            /* Skip nal_octet in nal_start to be overriden by FU header */
 
189
            ++nal_start;
 
190
        } else {
 
191
            /* Not the first fragment, get NRI and NAL unit type
 
192
             * from the previous fragment.
 
193
             */
 
194
            p = nal_start - pktz->cfg.mtu;
 
195
            NRI = (*p & 0x60) >> 5;
 
196
            TYPE = *(p+1) & 0x1F;
 
197
        }
 
198
 
 
199
        /* Init FU indicator (one octet: F+NRI+TYPE) */
 
200
        p = nal_start - HEADER_SIZE_FU_A;
 
201
        *p = (NRI << 5) | NAL_TYPE_FU_A;
 
202
        ++p;
 
203
 
 
204
        /* Init FU header (one octed: S+E+R+TYPE) */
 
205
        *p = TYPE;
 
206
        if (nal_octet)
 
207
            *p |= (1 << 7); /* S bit flag = start of fragmentation */
 
208
        if (nal_end-nal_start+HEADER_SIZE_FU_A <= pktz->cfg.mtu)
 
209
            *p |= (1 << 6); /* E bit flag = end of fragmentation */
 
210
 
 
211
        /* Set payload, payload length */
 
212
        *payload = nal_start - HEADER_SIZE_FU_A;
 
213
        if (nal_end-nal_start+HEADER_SIZE_FU_A > pktz->cfg.mtu)
 
214
            *payload_len = pktz->cfg.mtu;
 
215
        else
 
216
            *payload_len = nal_end - nal_start + HEADER_SIZE_FU_A;
 
217
        *pos = *payload + *payload_len - buf;
 
218
 
 
219
#if DBG_PACKETIZE
 
220
        PJ_LOG(3, ("h264pack", "Packetized fragmented H264 NAL unit "
 
221
                   "(pos=%d, type=%d, NRI=%d, S=%d, E=%d, len=%d/%d)",
 
222
                   *payload-buf, TYPE, NRI, *p>>7, (*p>>6)&1, *payload_len,
 
223
                   buf_len));
 
224
#endif
 
225
 
 
226
        return PJ_SUCCESS;
 
227
    }
 
228
 
 
229
    /* Aggregation (STAP-A) packet */
 
230
    if ((pktz->cfg.mode != PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL) &&
 
231
        (nal_end != end) &&
 
232
        (nal_end - nal_start + HEADER_SIZE_STAP_A) < pktz->cfg.mtu) 
 
233
    {
 
234
        int total_size;
 
235
        unsigned nal_cnt = 1;
 
236
        pj_uint8_t *nal[MAX_NALS_IN_AGGR];
 
237
        pj_size_t nal_size[MAX_NALS_IN_AGGR];
 
238
        pj_uint8_t NRI;
 
239
 
 
240
        pj_assert(nal_octet);
 
241
 
 
242
        /* Init the first NAL unit in the packet */
 
243
        nal[0] = nal_start;
 
244
        nal_size[0] = nal_end - nal_start;
 
245
        total_size = nal_size[0] + HEADER_SIZE_STAP_A;
 
246
        NRI = (*nal_octet & 0x60) >> 5;
 
247
 
 
248
        /* Populate next NAL units */
 
249
        while (nal_cnt < MAX_NALS_IN_AGGR) {
 
250
            pj_uint8_t *tmp_end;
 
251
 
 
252
            /* Find start address of the next NAL unit */
 
253
            p = nal[nal_cnt-1] + nal_size[nal_cnt-1];
 
254
            while (*p++ == 0);
 
255
            nal[nal_cnt] = p;
 
256
 
 
257
            /* Find end address of the next NAL unit */
 
258
            tmp_end = p + (pktz->cfg.mtu - total_size);
 
259
            if (tmp_end > end)
 
260
                tmp_end = end;
 
261
            p = find_next_nal_unit(p+1, tmp_end);
 
262
            if (p) {
 
263
                nal_size[nal_cnt] = p - nal[nal_cnt];
 
264
            } else {
 
265
                break;
 
266
            }
 
267
 
 
268
            /* Update total payload size (2 octet NAL size + NAL) */
 
269
            total_size += (2 + nal_size[nal_cnt]);
 
270
            if (total_size <= pktz->cfg.mtu) {
 
271
                pj_uint8_t tmp_nri;
 
272
 
 
273
                /* Get maximum NRI of the aggregated NAL units */
 
274
                tmp_nri = (*(nal[nal_cnt]-1) & 0x60) >> 5;
 
275
                if (tmp_nri > NRI)
 
276
                    NRI = tmp_nri;
 
277
            } else {
 
278
                break;
 
279
            }
 
280
 
 
281
            ++nal_cnt;
 
282
        }
 
283
 
 
284
        /* Only use STAP-A when we found more than one NAL units */
 
285
        if (nal_cnt > 1) {
 
286
            unsigned i;
 
287
 
 
288
            /* Init STAP-A NAL header (F+NRI+TYPE) */
 
289
            p = nal[0] - HEADER_SIZE_STAP_A;
 
290
            *p++ = (NRI << 5) | NAL_TYPE_STAP_A;
 
291
 
 
292
            /* Append all populated NAL units into payload (SIZE+NAL) */
 
293
            for (i = 0; i < nal_cnt; ++i) {
 
294
                /* Put size (2 octets in network order) */
 
295
                pj_assert(nal_size[i] <= 0xFFFF);
 
296
                *p++ = (pj_uint8_t)(nal_size[i] >> 8);
 
297
                *p++ = (pj_uint8_t)(nal_size[i] & 0xFF);
 
298
                
 
299
                /* Append NAL unit, watchout memmove()-ing bitstream! */
 
300
                if (p != nal[i])
 
301
                    pj_memmove(p, nal[i], nal_size[i]);
 
302
                p += nal_size[i];
 
303
            }
 
304
 
 
305
            /* Set payload, payload length, and pos */
 
306
            *payload = nal[0] - HEADER_SIZE_STAP_A;
 
307
            pj_assert(*payload >= buf+*pos);
 
308
            *payload_len = p - *payload;
 
309
            *pos = nal[nal_cnt-1] + nal_size[nal_cnt-1] - buf;
 
310
 
 
311
#if DBG_PACKETIZE
 
312
            PJ_LOG(3, ("h264pack", "Packetized aggregation of "
 
313
                       "%d H264 NAL units (pos=%d, NRI=%d len=%d/%d)",
 
314
                       nal_cnt, *payload-buf, NRI, *payload_len, buf_len));
 
315
#endif
 
316
 
 
317
            return PJ_SUCCESS;
 
318
        }
 
319
    }
 
320
 
 
321
    /* Single NAL unit packet */
 
322
    *payload = nal_start;
 
323
    *payload_len = nal_end - nal_start;
 
324
    *pos = nal_end - buf;
 
325
 
 
326
#if DBG_PACKETIZE
 
327
    PJ_LOG(3, ("h264pack", "Packetized single H264 NAL unit "
 
328
               "(pos=%d, type=%d, NRI=%d, len=%d/%d)",
 
329
               nal_start-buf, *nal_octet&0x1F, (*nal_octet&0x60)>>5,
 
330
               *payload_len, buf_len));
 
331
#endif
 
332
 
 
333
    return PJ_SUCCESS;
 
334
}
 
335
 
 
336
 
 
337
/*
 
338
 * Append RTP payload to a H.264 picture bitstream. Note that the only
 
339
 * payload format that cares about packet lost is the NAL unit
 
340
 * fragmentation format (FU-A/B), so we will only manage the "prev_lost"
 
341
 * state for the FU-A/B packets.
 
342
 */
 
343
PJ_DEF(pj_status_t) pjmedia_h264_unpacketize(pjmedia_h264_packetizer *pktz,
 
344
                                             const pj_uint8_t *payload,
 
345
                                             pj_size_t   payload_len,
 
346
                                             pj_uint8_t *bits,
 
347
                                             pj_size_t   bits_len,
 
348
                                             unsigned   *bits_pos)
 
349
{
 
350
    const pj_uint8_t nal_start_code[3] = {0, 0, 1};
 
351
    enum { MIN_PAYLOAD_SIZE = 2 };
 
352
    pj_uint8_t nal_type;
 
353
 
 
354
    PJ_UNUSED_ARG(pktz);
 
355
 
 
356
#if DBG_UNPACKETIZE
 
357
    if (*bits_pos == 0 && payload_len) {
 
358
        PJ_LOG(3, ("h264unpack", ">> Start unpacking new frame <<"));
 
359
    }
 
360
#endif
 
361
 
 
362
    /* Check if this is a missing/lost packet */
 
363
    if (payload == NULL) {
 
364
        pktz->unpack_prev_lost = PJ_TRUE;
 
365
        return PJ_SUCCESS;
 
366
    }
 
367
 
 
368
    /* H264 payload size */
 
369
    if (payload_len < MIN_PAYLOAD_SIZE) {
 
370
        /* Invalid bitstream, discard this payload */
 
371
        pktz->unpack_prev_lost = PJ_TRUE;
 
372
        return PJ_EINVAL;
 
373
    }
 
374
 
 
375
    /* Reset last sync point for every new picture bitstream */
 
376
    if (*bits_pos == 0)
 
377
        pktz->unpack_last_sync_pos = 0;
 
378
 
 
379
    nal_type = *payload & 0x1F;
 
380
    if (nal_type >= NAL_TYPE_SINGLE_NAL_MIN &&
 
381
        nal_type <= NAL_TYPE_SINGLE_NAL_MAX)
 
382
    {
 
383
        /* Single NAL unit packet */
 
384
        pj_uint8_t *p = bits + *bits_pos;
 
385
 
 
386
        /* Validate bitstream length */
 
387
        if (bits_len-*bits_pos < payload_len+PJ_ARRAY_SIZE(nal_start_code)) {
 
388
            /* Insufficient bistream buffer, discard this payload */
 
389
            pj_assert(!"Insufficient H.263 bitstream buffer");
 
390
            return PJ_ETOOSMALL;
 
391
        }
 
392
 
 
393
        /* Write NAL unit start code */
 
394
        pj_memcpy(p, &nal_start_code, PJ_ARRAY_SIZE(nal_start_code));
 
395
        p += PJ_ARRAY_SIZE(nal_start_code);
 
396
 
 
397
        /* Write NAL unit */
 
398
        pj_memcpy(p, payload, payload_len);
 
399
        p += payload_len;
 
400
 
 
401
        /* Update the bitstream writing offset */
 
402
        *bits_pos = p - bits;
 
403
        pktz->unpack_last_sync_pos = *bits_pos;
 
404
 
 
405
#if DBG_UNPACKETIZE
 
406
        PJ_LOG(3, ("h264unpack", "Unpacked single H264 NAL unit "
 
407
                   "(type=%d, NRI=%d, len=%d)",
 
408
                   nal_type, (*payload&0x60)>>5, payload_len));
 
409
#endif
 
410
 
 
411
    }
 
412
    else if (nal_type == NAL_TYPE_STAP_A)
 
413
    {
 
414
        /* Aggregation packet */
 
415
        pj_uint8_t *p, *p_end;
 
416
        const pj_uint8_t *q, *q_end;
 
417
        unsigned cnt = 0;
 
418
 
 
419
        /* Validate bitstream length */
 
420
        if (bits_len - *bits_pos < payload_len + 32) {
 
421
            /* Insufficient bistream buffer, discard this payload */
 
422
            pj_assert(!"Insufficient H.263 bitstream buffer");
 
423
            return PJ_ETOOSMALL;
 
424
        }
 
425
 
 
426
        /* Fill bitstream */
 
427
        p = bits + *bits_pos;
 
428
        p_end = bits + bits_len;
 
429
        q = payload + 1;
 
430
        q_end = payload + payload_len;
 
431
        while (q < q_end && p < p_end) {
 
432
            pj_uint16_t tmp_nal_size;
 
433
 
 
434
            /* Write NAL unit start code */
 
435
            pj_memcpy(p, &nal_start_code, PJ_ARRAY_SIZE(nal_start_code));
 
436
            p += PJ_ARRAY_SIZE(nal_start_code);
 
437
 
 
438
            /* Get NAL unit size */
 
439
            tmp_nal_size = (*q << 8) | *(q+1);
 
440
            q += 2;
 
441
            if (q + tmp_nal_size > q_end) {
 
442
                /* Invalid bitstream, discard the rest of the payload */
 
443
                return PJ_EINVAL;
 
444
            }
 
445
 
 
446
            /* Write NAL unit */
 
447
            pj_memcpy(p, q, tmp_nal_size);
 
448
            p += tmp_nal_size;
 
449
            q += tmp_nal_size;
 
450
            ++cnt;
 
451
 
 
452
            /* Update the bitstream writing offset */
 
453
            *bits_pos = p - bits;
 
454
            pktz->unpack_last_sync_pos = *bits_pos;
 
455
        }
 
456
 
 
457
#if DBG_UNPACKETIZE
 
458
        PJ_LOG(3, ("h264unpack", "Unpacked %d H264 NAL units (len=%d)",
 
459
                   cnt, payload_len));
 
460
#endif
 
461
 
 
462
    }
 
463
    else if (nal_type == NAL_TYPE_FU_A)
 
464
    {
 
465
        /* Fragmentation packet */
 
466
        pj_uint8_t *p;
 
467
        const pj_uint8_t *q = payload;
 
468
        pj_uint8_t NRI, TYPE, S, E;
 
469
 
 
470
        p = bits + *bits_pos;
 
471
 
 
472
        /* Validate bitstream length */
 
473
        if (bits_len-*bits_pos < payload_len+PJ_ARRAY_SIZE(nal_start_code)) {
 
474
            /* Insufficient bistream buffer, drop this packet */
 
475
            pj_assert(!"Insufficient H.263 bitstream buffer");
 
476
            pktz->unpack_prev_lost = PJ_TRUE;
 
477
            return PJ_ETOOSMALL;
 
478
        }
 
479
 
 
480
        /* Get info */
 
481
        S = *(q+1) & 0x80;    /* Start bit flag */
 
482
        E = *(q+1) & 0x40;    /* End bit flag   */
 
483
        TYPE = *(q+1) & 0x1f;
 
484
        NRI = (*q & 0x60) >> 5;
 
485
 
 
486
        /* Fill bitstream */
 
487
        if (S) {
 
488
            /* This is the first part, write NAL unit start code */
 
489
            pj_memcpy(p, &nal_start_code, PJ_ARRAY_SIZE(nal_start_code));
 
490
            p += PJ_ARRAY_SIZE(nal_start_code);
 
491
 
 
492
            /* Write NAL unit octet */
 
493
            *p++ = (NRI << 5) | TYPE;
 
494
        } else if (pktz->unpack_prev_lost) {
 
495
            /* If prev packet was lost, revert the bitstream pointer to
 
496
             * the last sync point.
 
497
             */
 
498
            pj_assert(pktz->unpack_last_sync_pos <= *bits_pos);
 
499
            *bits_pos = pktz->unpack_last_sync_pos;
 
500
            /* And discard this payload (and the following fragmentation
 
501
             * payloads carrying this same NAL unit.
 
502
             */
 
503
            return PJ_EIGNORED;
 
504
        }
 
505
        q += 2;
 
506
 
 
507
        /* Write NAL unit */
 
508
        pj_memcpy(p, q, payload_len - 2);
 
509
        p += (payload_len - 2);
 
510
 
 
511
        /* Update the bitstream writing offset */
 
512
        *bits_pos = p - bits;
 
513
        if (E) {
 
514
            /* Update the sync pos only if the end bit flag is set */
 
515
            pktz->unpack_last_sync_pos = *bits_pos;
 
516
        }
 
517
 
 
518
#if DBG_UNPACKETIZE
 
519
        PJ_LOG(3, ("h264unpack", "Unpacked fragmented H264 NAL unit "
 
520
                   "(type=%d, NRI=%d, len=%d)",
 
521
                   TYPE, NRI, payload_len));
 
522
#endif
 
523
 
 
524
    } else {
 
525
        *bits_pos = 0;
 
526
        return PJ_ENOTSUP;
 
527
    }
 
528
 
 
529
    pktz->unpack_prev_lost = PJ_FALSE;
 
530
 
 
531
    return PJ_SUCCESS;
 
532
}
 
533
 
 
534
 
 
535
#endif /* PJMEDIA_HAS_VIDEO */