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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.2.1/pjmedia/src/pjmedia/vid_stream.c

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: vid_stream.c 4613 2013-10-08 09:08:13Z bennylp $ */
 
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/vid_stream.h>
 
20
#include <pjmedia/errno.h>
 
21
#include <pjmedia/event.h>
 
22
#include <pjmedia/rtp.h>
 
23
#include <pjmedia/rtcp.h>
 
24
#include <pjmedia/jbuf.h>
 
25
#include <pjmedia/stream_common.h>
 
26
#include <pj/array.h>
 
27
#include <pj/assert.h>
 
28
#include <pj/compat/socket.h>
 
29
#include <pj/errno.h>
 
30
#include <pj/ioqueue.h>
 
31
#include <pj/log.h>
 
32
#include <pj/os.h>
 
33
#include <pj/pool.h>
 
34
#include <pj/rand.h>
 
35
#include <pj/sock_select.h>
 
36
#include <pj/string.h>      /* memcpy() */
 
37
 
 
38
 
 
39
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
 
40
 
 
41
 
 
42
#define THIS_FILE                       "vid_stream.c"
 
43
#define ERRLEVEL                        1
 
44
#define LOGERR_(expr)                   stream_perror expr
 
45
#define TRC_(expr)                      PJ_LOG(5,expr)
 
46
#define SIGNATURE                       PJMEDIA_SIG_PORT_VID_STREAM
 
47
 
 
48
#define TRACE_RC                        0
 
49
 
 
50
/* Tracing jitter buffer operations in a stream session to a CSV file.
 
51
 * The trace will contain JB operation timestamp, frame info, RTP info, and
 
52
 * the JB state right after the operation.
 
53
 */
 
54
#define TRACE_JB                        0       /* Enable/disable trace.    */
 
55
#define TRACE_JB_PATH_PREFIX            ""      /* Optional path/prefix
 
56
                                                   for the CSV filename.    */
 
57
#if TRACE_JB
 
58
#   include <pj/file_io.h>
 
59
#   define TRACE_JB_INVALID_FD          ((pj_oshandle_t)-1)
 
60
#   define TRACE_JB_OPENED(s)           (s->trace_jb_fd != TRACE_JB_INVALID_FD)
 
61
#endif
 
62
 
 
63
#ifndef PJMEDIA_VSTREAM_SIZE
 
64
#   define PJMEDIA_VSTREAM_SIZE 1000
 
65
#endif
 
66
 
 
67
#ifndef PJMEDIA_VSTREAM_INC
 
68
#   define PJMEDIA_VSTREAM_INC  1000
 
69
#endif
 
70
 
 
71
/* Due to network MTU limitation, a picture bitstream may be splitted into
 
72
 * several chunks for RTP delivery. The chunk number may vary depend on the
 
73
 * picture resolution and MTU. This constant specifies the minimum chunk
 
74
 * number to be allocated to store a picture bitstream in decoding direction.
 
75
 */
 
76
#define MIN_CHUNKS_PER_FRM      30
 
77
 
 
78
/* Video stream keep-alive feature is currently disabled. */
 
79
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
 
80
#   undef PJMEDIA_STREAM_ENABLE_KA
 
81
#   define PJMEDIA_STREAM_ENABLE_KA 0
 
82
#endif
 
83
 
 
84
 
 
85
/**
 
86
 * Media channel.
 
87
 */
 
88
typedef struct pjmedia_vid_channel
 
89
{
 
90
    pjmedia_vid_stream     *stream;         /**< Parent stream.             */
 
91
    pjmedia_dir             dir;            /**< Channel direction.         */
 
92
    pjmedia_port            port;           /**< Port interface.            */
 
93
    unsigned                pt;             /**< Payload type.              */
 
94
    pj_bool_t               paused;         /**< Paused?.                   */
 
95
    void                   *buf;            /**< Output buffer.             */
 
96
    unsigned                buf_size;       /**< Size of output buffer.     */
 
97
    pjmedia_rtp_session     rtp;            /**< RTP session.               */
 
98
} pjmedia_vid_channel;
 
99
 
 
100
 
 
101
/**
 
102
 * This structure describes media stream.
 
103
 * A media stream is bidirectional media transmission between two endpoints.
 
104
 * It consists of two channels, i.e. encoding and decoding channels.
 
105
 * A media stream corresponds to a single "m=" line in a SDP session
 
106
 * description.
 
107
 */
 
108
struct pjmedia_vid_stream
 
109
{
 
110
    pj_pool_t               *own_pool;      /**< Internal pool.             */
 
111
    pjmedia_endpt           *endpt;         /**< Media endpoint.            */
 
112
    pjmedia_vid_codec_mgr   *codec_mgr;     /**< Codec manager.             */
 
113
    pjmedia_vid_stream_info  info;          /**< Stream info.               */
 
114
 
 
115
    pjmedia_vid_channel     *enc;           /**< Encoding channel.          */
 
116
    pjmedia_vid_channel     *dec;           /**< Decoding channel.          */
 
117
 
 
118
    pjmedia_dir              dir;           /**< Stream direction.          */
 
119
    void                    *user_data;     /**< User data.                 */
 
120
    pj_str_t                 name;          /**< Stream name                */
 
121
    pj_str_t                 cname;         /**< SDES CNAME                 */
 
122
 
 
123
    pjmedia_transport       *transport;     /**< Stream transport.          */
 
124
    unsigned                 send_err_cnt;  /**< Send error count.          */
 
125
 
 
126
    pj_mutex_t              *jb_mutex;
 
127
    pjmedia_jbuf            *jb;            /**< Jitter buffer.             */
 
128
    char                     jb_last_frm;   /**< Last frame type from jb    */
 
129
    unsigned                 jb_last_frm_cnt;/**< Last JB frame type counter*/
 
130
 
 
131
    pjmedia_rtcp_session     rtcp;          /**< RTCP for incoming RTP.     */
 
132
    pj_uint32_t              rtcp_last_tx;  /**< RTCP tx time in timestamp  */
 
133
    pj_uint32_t              rtcp_interval; /**< Interval, in timestamp.    */
 
134
    pj_bool_t                initial_rr;    /**< Initial RTCP RR sent       */
 
135
    pj_bool_t                rtcp_sdes_bye_disabled;/**< Send RTCP SDES/BYE?*/
 
136
    void                    *out_rtcp_pkt;  /**< Outgoing RTCP packet.      */
 
137
    unsigned                 out_rtcp_pkt_size;
 
138
                                            /**< Outgoing RTCP packet size. */
 
139
 
 
140
    unsigned                 dec_max_size;  /**< Size of decoded/raw picture*/
 
141
    pjmedia_ratio            dec_max_fps;   /**< Max fps of decoding dir.   */
 
142
    pjmedia_frame            dec_frame;     /**< Current decoded frame.     */
 
143
    pjmedia_event            fmt_event;     /**< Buffered fmt_changed event
 
144
                                                 to avoid deadlock          */
 
145
    pjmedia_event            miss_keyframe_event; 
 
146
                                            /**< Buffered missing keyframe
 
147
                                                 event for delayed republish*/
 
148
 
 
149
    unsigned                 frame_size;    /**< Size of encoded base frame.*/
 
150
    unsigned                 frame_ts_len;  /**< Frame length in timestamp. */
 
151
 
 
152
    unsigned                 rx_frame_cnt;  /**< # of array in rx_frames    */
 
153
    pjmedia_frame           *rx_frames;     /**< Temp. buffer for incoming
 
154
                                                 frame assembly.            */
 
155
 
 
156
    pj_bool_t                force_keyframe;/**< Forced to encode keyframe? */
 
157
 
 
158
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
 
159
    pj_bool_t                use_ka;           /**< Stream keep-alive with non-
 
160
                                                    codec-VAD mechanism is
 
161
                                                    enabled?                */
 
162
    pj_timestamp             last_frm_ts_sent; /**< Timestamp of last sending
 
163
                                                    packet                  */
 
164
#endif
 
165
 
 
166
#if TRACE_JB
 
167
    pj_oshandle_t            trace_jb_fd;   /**< Jitter tracing file handle.*/
 
168
    char                    *trace_jb_buf;  /**< Jitter tracing buffer.     */
 
169
#endif
 
170
 
 
171
    pjmedia_vid_codec       *codec;         /**< Codec instance being used. */
 
172
    pj_uint32_t              last_dec_ts;   /**< Last decoded timestamp.    */
 
173
    int                      last_dec_seq;  /**< Last decoded sequence.     */
 
174
 
 
175
 
 
176
    pj_timestamp             ts_freq;       /**< Timestamp frequency.       */
 
177
 
 
178
#if TRACE_RC
 
179
    unsigned                 rc_total_sleep;
 
180
    unsigned                 rc_total_pkt;
 
181
    unsigned                 rc_total_img;
 
182
    pj_timestamp             tx_start;
 
183
    pj_timestamp             tx_end;
 
184
#endif
 
185
};
 
186
 
 
187
/* Prototypes */
 
188
static pj_status_t decode_frame(pjmedia_vid_stream *stream,
 
189
                                pjmedia_frame *frame);
 
190
 
 
191
/*
 
192
 * Print error.
 
193
 */
 
194
static void stream_perror(const char *sender, const char *title,
 
195
                          pj_status_t status)
 
196
{
 
197
    char errmsg[PJ_ERR_MSG_SIZE];
 
198
 
 
199
    pj_strerror(status, errmsg, sizeof(errmsg));
 
200
    PJ_LOG(4,(sender, "%s: %s [err:%d]", title, errmsg, status));
 
201
}
 
202
 
 
203
 
 
204
static pj_status_t send_rtcp(pjmedia_vid_stream *stream,
 
205
                             pj_bool_t with_sdes,
 
206
                             pj_bool_t with_bye);
 
207
 
 
208
 
 
209
#if TRACE_JB
 
210
 
 
211
PJ_INLINE(int) trace_jb_print_timestamp(char **buf, pj_ssize_t len)
 
212
{
 
213
    pj_time_val now;
 
214
    pj_parsed_time ptime;
 
215
    char *p = *buf;
 
216
 
 
217
    if (len < 14)
 
218
        return -1;
 
219
 
 
220
    pj_gettimeofday(&now);
 
221
    pj_time_decode(&now, &ptime);
 
222
    p += pj_utoa_pad(ptime.hour, p, 2, '0');
 
223
    *p++ = ':';
 
224
    p += pj_utoa_pad(ptime.min, p, 2, '0');
 
225
    *p++ = ':';
 
226
    p += pj_utoa_pad(ptime.sec, p, 2, '0');
 
227
    *p++ = '.';
 
228
    p += pj_utoa_pad(ptime.msec, p, 3, '0');
 
229
    *p++ = ',';
 
230
 
 
231
    *buf = p;
 
232
 
 
233
    return 0;
 
234
}
 
235
 
 
236
PJ_INLINE(int) trace_jb_print_state(pjmedia_vid_stream *stream, 
 
237
                                    char **buf, pj_ssize_t len)
 
238
{
 
239
    char *p = *buf;
 
240
    char *endp = *buf + len;
 
241
    pjmedia_jb_state state;
 
242
 
 
243
    pjmedia_jbuf_get_state(stream->jb, &state);
 
244
 
 
245
    len = pj_ansi_snprintf(p, endp-p, "%d, %d, %d",
 
246
                           state.size, state.burst, state.prefetch);
 
247
    if ((len < 0) || (len >= endp-p))
 
248
        return -1;
 
249
 
 
250
    p += len;
 
251
    *buf = p;
 
252
    return 0;
 
253
}
 
254
 
 
255
static void trace_jb_get(pjmedia_vid_stream *stream, pjmedia_jb_frame_type ft,
 
256
                         pj_size_t fsize)
 
257
{
 
258
    char *p = stream->trace_jb_buf;
 
259
    char *endp = stream->trace_jb_buf + PJ_LOG_MAX_SIZE;
 
260
    pj_ssize_t len = 0;
 
261
    const char* ft_st;
 
262
 
 
263
    if (!TRACE_JB_OPENED(stream))
 
264
        return;
 
265
 
 
266
    /* Print timestamp. */
 
267
    if (trace_jb_print_timestamp(&p, endp-p))
 
268
        goto on_insuff_buffer;
 
269
 
 
270
    /* Print frame type and size */
 
271
    switch(ft) {
 
272
        case PJMEDIA_JB_MISSING_FRAME:
 
273
            ft_st = "missing";
 
274
            break;
 
275
        case PJMEDIA_JB_NORMAL_FRAME:
 
276
            ft_st = "normal";
 
277
            break;
 
278
        case PJMEDIA_JB_ZERO_PREFETCH_FRAME:
 
279
            ft_st = "prefetch";
 
280
            break;
 
281
        case PJMEDIA_JB_ZERO_EMPTY_FRAME:
 
282
            ft_st = "empty";
 
283
            break;
 
284
        default:
 
285
            ft_st = "unknown";
 
286
            break;
 
287
    }
 
288
 
 
289
    /* Print operation, size, frame count, frame type */
 
290
    len = pj_ansi_snprintf(p, endp-p, "GET,%d,1,%s,,,,", fsize, ft_st);
 
291
    if ((len < 0) || (len >= endp-p))
 
292
        goto on_insuff_buffer;
 
293
    p += len;
 
294
 
 
295
    /* Print JB state */
 
296
    if (trace_jb_print_state(stream, &p, endp-p))
 
297
        goto on_insuff_buffer;
 
298
 
 
299
    /* Print end of line */
 
300
    if (endp-p < 2)
 
301
        goto on_insuff_buffer;
 
302
    *p++ = '\n';
 
303
 
 
304
    /* Write and flush */
 
305
    len = p - stream->trace_jb_buf;
 
306
    pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len);
 
307
    pj_file_flush(stream->trace_jb_fd);
 
308
    return;
 
309
 
 
310
on_insuff_buffer:
 
311
    pj_assert(!"Trace buffer too small, check PJ_LOG_MAX_SIZE!");
 
312
}
 
313
 
 
314
static void trace_jb_put(pjmedia_vid_stream *stream,
 
315
                         const pjmedia_rtp_hdr *hdr,
 
316
                         unsigned payloadlen, unsigned frame_cnt)
 
317
{
 
318
    char *p = stream->trace_jb_buf;
 
319
    char *endp = stream->trace_jb_buf + PJ_LOG_MAX_SIZE;
 
320
    pj_ssize_t len = 0;
 
321
 
 
322
    if (!TRACE_JB_OPENED(stream))
 
323
        return;
 
324
 
 
325
    /* Print timestamp. */
 
326
    if (trace_jb_print_timestamp(&p, endp-p))
 
327
        goto on_insuff_buffer;
 
328
 
 
329
    /* Print operation, size, frame count, RTP info */
 
330
    len = pj_ansi_snprintf(p, endp-p,
 
331
                           "PUT,%d,%d,,%d,%d,%d,",
 
332
                           payloadlen, frame_cnt,
 
333
                           pj_ntohs(hdr->seq), pj_ntohl(hdr->ts), hdr->m);
 
334
    if ((len < 0) || (len >= endp-p))
 
335
        goto on_insuff_buffer;
 
336
    p += len;
 
337
 
 
338
    /* Print JB state */
 
339
    if (trace_jb_print_state(stream, &p, endp-p))
 
340
        goto on_insuff_buffer;
 
341
 
 
342
    /* Print end of line */
 
343
    if (endp-p < 2)
 
344
        goto on_insuff_buffer;
 
345
    *p++ = '\n';
 
346
 
 
347
    /* Write and flush */
 
348
    len = p - stream->trace_jb_buf;
 
349
    pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len);
 
350
    pj_file_flush(stream->trace_jb_fd);
 
351
    return;
 
352
 
 
353
on_insuff_buffer:
 
354
    pj_assert(!"Trace buffer too small, check PJ_LOG_MAX_SIZE!");
 
355
}
 
356
 
 
357
#endif /* TRACE_JB */
 
358
 
 
359
static void dump_port_info(const pjmedia_vid_channel *chan,
 
360
                           const char *event_name)
 
361
{
 
362
    const pjmedia_port_info *pi = &chan->port.info;
 
363
    char fourcc_name[5];
 
364
 
 
365
    PJ_LOG(5, (pi->name.ptr,
 
366
               " %s format %s: %dx%d %s%s %d/%d(~%d)fps",
 
367
               (chan->dir==PJMEDIA_DIR_DECODING? "Decoding":"Encoding"),
 
368
               event_name,
 
369
               pi->fmt.det.vid.size.w, pi->fmt.det.vid.size.h,
 
370
               pjmedia_fourcc_name(pi->fmt.id, fourcc_name),
 
371
               (chan->dir==PJMEDIA_DIR_ENCODING?"->":"<-"),
 
372
               pi->fmt.det.vid.fps.num, pi->fmt.det.vid.fps.denum,
 
373
               pi->fmt.det.vid.fps.num/pi->fmt.det.vid.fps.denum));
 
374
}
 
375
 
 
376
/*
 
377
 * Handle events from stream components.
 
378
 */
 
379
static pj_status_t stream_event_cb(pjmedia_event *event,
 
380
                                   void *user_data)
 
381
{
 
382
    pjmedia_vid_stream *stream = (pjmedia_vid_stream*)user_data;
 
383
 
 
384
    if (event->epub == stream->codec) {
 
385
        /* This is codec event */
 
386
        switch (event->type) {
 
387
        case PJMEDIA_EVENT_FMT_CHANGED:
 
388
            /* Copy the event to avoid deadlock if we publish the event
 
389
             * now. This happens because fmt_event may trigger restart
 
390
             * while we're still holding the jb_mutex.
 
391
             */
 
392
            pj_memcpy(&stream->fmt_event, event, sizeof(*event));
 
393
            return PJ_SUCCESS;
 
394
 
 
395
        case PJMEDIA_EVENT_KEYFRAME_MISSING:
 
396
            /* Republish this event later from get_frame(). */
 
397
            pj_memcpy(&stream->miss_keyframe_event, event, sizeof(*event));
 
398
            return PJ_SUCCESS;
 
399
 
 
400
        default:
 
401
            break;
 
402
        }
 
403
    }
 
404
 
 
405
    return pjmedia_event_publish(NULL, stream, event, 0);
 
406
}
 
407
 
 
408
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
 
409
/*
 
410
 * Send keep-alive packet using non-codec frame.
 
411
 */
 
412
static void send_keep_alive_packet(pjmedia_vid_stream *stream)
 
413
{
 
414
#if PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_EMPTY_RTP
 
415
 
 
416
    /* Keep-alive packet is empty RTP */
 
417
    pjmedia_vid_channel *channel = stream->enc;
 
418
    pj_status_t status;
 
419
    void *pkt;
 
420
    int pkt_len;
 
421
 
 
422
    TRC_((channel->port.info.name.ptr,
 
423
          "Sending keep-alive (RTCP and empty RTP)"));
 
424
 
 
425
    /* Send RTP */
 
426
    status = pjmedia_rtp_encode_rtp( &stream->enc->rtp,
 
427
                                     stream->enc->pt, 0,
 
428
                                     1,
 
429
                                     0,
 
430
                                     (const void**)&pkt,
 
431
                                     &pkt_len);
 
432
    pj_assert(status == PJ_SUCCESS);
 
433
 
 
434
    pj_memcpy(stream->enc->buf, pkt, pkt_len);
 
435
    pjmedia_transport_send_rtp(stream->transport, stream->enc->buf,
 
436
                               pkt_len);
 
437
 
 
438
    /* Send RTCP */
 
439
    send_rtcp(stream, PJ_TRUE, PJ_FALSE);
 
440
 
 
441
#elif PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_USER
 
442
 
 
443
    /* Keep-alive packet is defined in PJMEDIA_STREAM_KA_USER_PKT */
 
444
    pjmedia_vid_channel *channel = stream->enc;
 
445
    int pkt_len;
 
446
    const pj_str_t str_ka = PJMEDIA_STREAM_KA_USER_PKT;
 
447
 
 
448
    TRC_((channel->port.info.name.ptr,
 
449
          "Sending keep-alive (custom RTP/RTCP packets)"));
 
450
 
 
451
    /* Send to RTP port */
 
452
    pj_memcpy(stream->enc->buf, str_ka.ptr, str_ka.slen);
 
453
    pkt_len = str_ka.slen;
 
454
    pjmedia_transport_send_rtp(stream->transport, stream->enc->buf,
 
455
                               pkt_len);
 
456
 
 
457
    /* Send to RTCP port */
 
458
    pjmedia_transport_send_rtcp(stream->transport, stream->enc->buf,
 
459
                                pkt_len);
 
460
 
 
461
#else
 
462
    
 
463
    PJ_UNUSED_ARG(stream);
 
464
 
 
465
#endif
 
466
}
 
467
#endif  /* defined(PJMEDIA_STREAM_ENABLE_KA) */
 
468
 
 
469
 
 
470
static pj_status_t send_rtcp(pjmedia_vid_stream *stream,
 
471
                             pj_bool_t with_sdes,
 
472
                             pj_bool_t with_bye)
 
473
{
 
474
    void *sr_rr_pkt;
 
475
    pj_uint8_t *pkt;
 
476
    int len, max_len;
 
477
    pj_status_t status;
 
478
 
 
479
    /* Build RTCP RR/SR packet */
 
480
    pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len);
 
481
 
 
482
    if (with_sdes || with_bye) {
 
483
        pkt = (pj_uint8_t*) stream->out_rtcp_pkt;
 
484
        pj_memcpy(pkt, sr_rr_pkt, len);
 
485
        max_len = stream->out_rtcp_pkt_size;
 
486
    } else {
 
487
        pkt = (pj_uint8_t*)sr_rr_pkt;
 
488
        max_len = len;
 
489
    }
 
490
 
 
491
    /* Build RTCP SDES packet */
 
492
    if (with_sdes) {
 
493
        pjmedia_rtcp_sdes sdes;
 
494
        pj_size_t sdes_len;
 
495
 
 
496
        pj_bzero(&sdes, sizeof(sdes));
 
497
        sdes.cname = stream->cname;
 
498
        sdes_len = max_len - len;
 
499
        status = pjmedia_rtcp_build_rtcp_sdes(&stream->rtcp, pkt+len,
 
500
                                              &sdes_len, &sdes);
 
501
        if (status != PJ_SUCCESS) {
 
502
            PJ_PERROR(4,(stream->name.ptr, status,
 
503
                                     "Error generating RTCP SDES"));
 
504
        } else {
 
505
            len += (int)sdes_len;
 
506
        }
 
507
    }
 
508
 
 
509
    /* Build RTCP BYE packet */
 
510
    if (with_bye) {
 
511
        pj_size_t bye_len;
 
512
 
 
513
        bye_len = max_len - len;
 
514
        status = pjmedia_rtcp_build_rtcp_bye(&stream->rtcp, pkt+len,
 
515
                                             &bye_len, NULL);
 
516
        if (status != PJ_SUCCESS) {
 
517
            PJ_PERROR(4,(stream->name.ptr, status,
 
518
                                     "Error generating RTCP BYE"));
 
519
        } else {
 
520
            len += (int)bye_len;
 
521
        }
 
522
    }
 
523
 
 
524
    /* Send! */
 
525
    status = pjmedia_transport_send_rtcp(stream->transport, pkt, len);
 
526
 
 
527
    return status;
 
528
}
 
529
 
 
530
 
 
531
/**
 
532
 * check_tx_rtcp()
 
533
 *
 
534
 * This function is can be called by either put_frame() or get_frame(),
 
535
 * to transmit periodic RTCP SR/RR report.
 
536
 */
 
537
static void check_tx_rtcp(pjmedia_vid_stream *stream, pj_uint32_t timestamp)
 
538
{
 
539
    /* Note that timestamp may represent local or remote timestamp, 
 
540
     * depending on whether this function is called from put_frame()
 
541
     * or get_frame().
 
542
     */
 
543
 
 
544
 
 
545
    if (stream->rtcp_last_tx == 0) {
 
546
        
 
547
        stream->rtcp_last_tx = timestamp;
 
548
 
 
549
    } else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) {
 
550
        pj_status_t status;
 
551
        
 
552
        status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE);
 
553
        if (status != PJ_SUCCESS) {
 
554
            PJ_PERROR(4,(stream->name.ptr, status,
 
555
                         "Error sending RTCP"));
 
556
        }
 
557
 
 
558
        stream->rtcp_last_tx = timestamp;
 
559
    }
 
560
}
 
561
 
 
562
 
 
563
#if 0
 
564
static void dump_bin(const char *buf, unsigned len)
 
565
{
 
566
    unsigned i;
 
567
 
 
568
    PJ_LOG(3,(THIS_FILE, "begin dump"));
 
569
    for (i=0; i<len; ++i) {
 
570
        int j;
 
571
        char bits[9];
 
572
        unsigned val = buf[i] & 0xFF;
 
573
 
 
574
        bits[8] = '\0';
 
575
        for (j=0; j<8; ++j) {
 
576
            if (val & (1 << (7-j)))
 
577
                bits[j] = '1';
 
578
            else
 
579
                bits[j] = '0';
 
580
        }
 
581
 
 
582
        PJ_LOG(3,(THIS_FILE, "%2d %s [%d]", i, bits, val));
 
583
    }
 
584
    PJ_LOG(3,(THIS_FILE, "end dump"));
 
585
}
 
586
#endif
 
587
 
 
588
 
 
589
/*
 
590
 * This callback is called by stream transport on receipt of packets
 
591
 * in the RTP socket. 
 
592
 */
 
593
static void on_rx_rtp( void *data, 
 
594
                       void *pkt,
 
595
                       pj_ssize_t bytes_read)
 
596
 
 
597
{
 
598
    pjmedia_vid_stream *stream = (pjmedia_vid_stream*) data;
 
599
    pjmedia_vid_channel *channel = stream->dec;
 
600
    const pjmedia_rtp_hdr *hdr;
 
601
    const void *payload;
 
602
    unsigned payloadlen;
 
603
    pjmedia_rtp_status seq_st;
 
604
    pj_status_t status;
 
605
    pj_bool_t pkt_discarded = PJ_FALSE;
 
606
 
 
607
    /* Check for errors */
 
608
    if (bytes_read < 0) {
 
609
        LOGERR_((channel->port.info.name.ptr, "RTP recv() error", 
 
610
                (pj_status_t)-bytes_read));
 
611
        return;
 
612
    }
 
613
 
 
614
    /* Ignore keep-alive packets */
 
615
    if (bytes_read < (pj_ssize_t) sizeof(pjmedia_rtp_hdr))
 
616
        return;
 
617
 
 
618
    /* Update RTP and RTCP session. */
 
619
    status = pjmedia_rtp_decode_rtp(&channel->rtp, pkt, (int)bytes_read,
 
620
                                    &hdr, &payload, &payloadlen);
 
621
    if (status != PJ_SUCCESS) {
 
622
        LOGERR_((channel->port.info.name.ptr, "RTP decode error", status));
 
623
        stream->rtcp.stat.rx.discard++;
 
624
        return;
 
625
    }
 
626
 
 
627
    /* Ignore the packet if decoder is paused */
 
628
    if (channel->paused)
 
629
        goto on_return;
 
630
 
 
631
    /* Update RTP session (also checks if RTP session can accept
 
632
     * the incoming packet.
 
633
     */
 
634
    pjmedia_rtp_session_update2(&channel->rtp, hdr, &seq_st, PJ_TRUE);
 
635
    if (seq_st.status.value) {
 
636
        TRC_  ((channel->port.info.name.ptr, 
 
637
                "RTP status: badpt=%d, badssrc=%d, dup=%d, "
 
638
                "outorder=%d, probation=%d, restart=%d", 
 
639
                seq_st.status.flag.badpt,
 
640
                seq_st.status.flag.badssrc,
 
641
                seq_st.status.flag.dup,
 
642
                seq_st.status.flag.outorder,
 
643
                seq_st.status.flag.probation,
 
644
                seq_st.status.flag.restart));
 
645
 
 
646
        if (seq_st.status.flag.badpt) {
 
647
            PJ_LOG(4,(channel->port.info.name.ptr,
 
648
                      "Bad RTP pt %d (expecting %d)",
 
649
                      hdr->pt, channel->rtp.out_pt));
 
650
        }
 
651
 
 
652
        if (seq_st.status.flag.badssrc) {
 
653
            PJ_LOG(4,(channel->port.info.name.ptr,
 
654
                      "Changed RTP peer SSRC %d (previously %d)",
 
655
                      channel->rtp.peer_ssrc, stream->rtcp.peer_ssrc));
 
656
            stream->rtcp.peer_ssrc = channel->rtp.peer_ssrc;
 
657
        }
 
658
 
 
659
 
 
660
    }
 
661
 
 
662
    /* Skip bad RTP packet */
 
663
    if (seq_st.status.flag.bad) {
 
664
        pkt_discarded = PJ_TRUE;
 
665
        goto on_return;
 
666
    }
 
667
 
 
668
    /* Ignore if payloadlen is zero */
 
669
    if (payloadlen == 0) {
 
670
        pkt_discarded = PJ_TRUE;
 
671
        goto on_return;
 
672
    }
 
673
 
 
674
    pj_mutex_lock( stream->jb_mutex );
 
675
 
 
676
    /* Quickly see if there may be a full picture in the jitter buffer, and
 
677
     * decode them if so. More thorough check will be done in decode_frame().
 
678
     */
 
679
    if ((pj_ntohl(hdr->ts) != stream->dec_frame.timestamp.u32.lo) || hdr->m) {
 
680
        if (PJMEDIA_VID_STREAM_SKIP_PACKETS_TO_REDUCE_LATENCY) {
 
681
            /* Always decode whenever we have picture in jb and
 
682
             * overwrite already decoded picture if necessary
 
683
             */
 
684
            pj_size_t old_size = stream->dec_frame.size;
 
685
 
 
686
            stream->dec_frame.size = stream->dec_max_size;
 
687
            if (decode_frame(stream, &stream->dec_frame) != PJ_SUCCESS) {
 
688
                stream->dec_frame.size = old_size;
 
689
            }
 
690
        } else {
 
691
            /* Only decode if we don't already have decoded one,
 
692
             * unless the jb is full.
 
693
             */
 
694
            pj_bool_t can_decode = PJ_FALSE;
 
695
 
 
696
            if (pjmedia_jbuf_is_full(stream->jb)) {
 
697
                can_decode = PJ_TRUE;
 
698
            }
 
699
            else if (stream->dec_frame.size == 0) {
 
700
                can_decode = PJ_TRUE;
 
701
            }
 
702
 
 
703
            if (can_decode) {
 
704
                stream->dec_frame.size = stream->dec_max_size;
 
705
                if (decode_frame(stream, &stream->dec_frame) != PJ_SUCCESS) {
 
706
                    stream->dec_frame.size = 0;
 
707
                }
 
708
            }
 
709
        }
 
710
    }
 
711
 
 
712
    /* Put "good" packet to jitter buffer, or reset the jitter buffer
 
713
     * when RTP session is restarted.
 
714
     */
 
715
    if (seq_st.status.flag.restart) {
 
716
        status = pjmedia_jbuf_reset(stream->jb);
 
717
        PJ_LOG(4,(channel->port.info.name.ptr, "Jitter buffer reset"));
 
718
    } else {
 
719
        /* Just put the payload into jitter buffer */
 
720
        pjmedia_jbuf_put_frame3(stream->jb, payload, payloadlen, 0, 
 
721
                                pj_ntohs(hdr->seq), pj_ntohl(hdr->ts), NULL);
 
722
 
 
723
#if TRACE_JB
 
724
        trace_jb_put(stream, hdr, payloadlen, count);
 
725
#endif
 
726
 
 
727
    }
 
728
    pj_mutex_unlock( stream->jb_mutex );
 
729
 
 
730
 
 
731
    /* Check if now is the time to transmit RTCP SR/RR report.
 
732
     * We only do this when stream direction is "decoding only", 
 
733
     * because otherwise check_tx_rtcp() will be handled by put_frame()
 
734
     */
 
735
    if (stream->dir == PJMEDIA_DIR_DECODING) {
 
736
        check_tx_rtcp(stream, pj_ntohl(hdr->ts));
 
737
    }
 
738
 
 
739
    if (status != 0) {
 
740
        LOGERR_((channel->port.info.name.ptr, "Jitter buffer put() error", 
 
741
                status));
 
742
        pkt_discarded = PJ_TRUE;
 
743
        goto on_return;
 
744
    }
 
745
 
 
746
on_return:
 
747
    /* Update RTCP session */
 
748
    if (stream->rtcp.peer_ssrc == 0)
 
749
        stream->rtcp.peer_ssrc = channel->rtp.peer_ssrc;
 
750
 
 
751
    pjmedia_rtcp_rx_rtp2(&stream->rtcp, pj_ntohs(hdr->seq),
 
752
                         pj_ntohl(hdr->ts), payloadlen, pkt_discarded);
 
753
 
 
754
    /* Send RTCP RR and SDES after we receive some RTP packets */
 
755
    if (stream->rtcp.received >= 10 && !stream->initial_rr) {
 
756
        status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled,
 
757
                           PJ_FALSE);
 
758
        if (status != PJ_SUCCESS) {
 
759
            PJ_PERROR(4,(stream->name.ptr, status,
 
760
                     "Error sending initial RTCP RR"));
 
761
        } else {
 
762
            stream->initial_rr = PJ_TRUE;
 
763
        }
 
764
    }
 
765
}
 
766
 
 
767
 
 
768
/*
 
769
 * This callback is called by stream transport on receipt of packets
 
770
 * in the RTCP socket. 
 
771
 */
 
772
static void on_rx_rtcp( void *data,
 
773
                        void *pkt, 
 
774
                        pj_ssize_t bytes_read)
 
775
{
 
776
    pjmedia_vid_stream *stream = (pjmedia_vid_stream*) data;
 
777
 
 
778
    /* Check for errors */
 
779
    if (bytes_read < 0) {
 
780
        LOGERR_((stream->cname.ptr, "RTCP recv() error", 
 
781
                 (pj_status_t)-bytes_read));
 
782
        return;
 
783
    }
 
784
 
 
785
    pjmedia_rtcp_rx_rtcp(&stream->rtcp, pkt, bytes_read);
 
786
}
 
787
 
 
788
static pj_status_t put_frame(pjmedia_port *port,
 
789
                             pjmedia_frame *frame)
 
790
{
 
791
    pjmedia_vid_stream *stream = (pjmedia_vid_stream*) port->port_data.pdata;
 
792
    pjmedia_vid_channel *channel = stream->enc;
 
793
    pj_status_t status = 0;
 
794
    pjmedia_frame frame_out;
 
795
    unsigned rtp_ts_len;
 
796
    void *rtphdr;
 
797
    int rtphdrlen;
 
798
    pj_bool_t has_more_data = PJ_FALSE;
 
799
    pj_size_t total_sent = 0;
 
800
    pjmedia_vid_encode_opt enc_opt;
 
801
    unsigned pkt_cnt = 0;
 
802
    pj_timestamp initial_time;
 
803
 
 
804
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
 
805
    /* If the interval since last sending packet is greater than
 
806
     * PJMEDIA_STREAM_KA_INTERVAL, send keep-alive packet.
 
807
     */
 
808
    if (stream->use_ka)
 
809
    {
 
810
        pj_uint32_t dtx_duration;
 
811
 
 
812
        dtx_duration = pj_timestamp_diff32(&stream->last_frm_ts_sent, 
 
813
                                           &frame->timestamp);
 
814
        /* Video stream keep-alive feature is currently disabled. */
 
815
        /*
 
816
        if (dtx_duration >
 
817
            PJMEDIA_STREAM_KA_INTERVAL *
 
818
            PJMEDIA_PIA_SRATE(&channel->port.info))
 
819
        {
 
820
            send_keep_alive_packet(stream);
 
821
            stream->last_frm_ts_sent = frame->timestamp;
 
822
        }
 
823
        */
 
824
    }
 
825
#endif
 
826
 
 
827
    /* Don't do anything if stream is paused */
 
828
    if (channel->paused) {
 
829
        return PJ_SUCCESS;
 
830
    }
 
831
 
 
832
    /* Get frame length in timestamp unit */
 
833
    rtp_ts_len = stream->frame_ts_len;
 
834
 
 
835
    /* Init frame_out buffer. */
 
836
    frame_out.buf = ((char*)channel->buf) + sizeof(pjmedia_rtp_hdr);
 
837
    frame_out.size = 0;
 
838
 
 
839
    /* Init encoding option */
 
840
    pj_bzero(&enc_opt, sizeof(enc_opt));
 
841
    if (stream->force_keyframe) {
 
842
        /* Force encoder to generate keyframe */
 
843
        enc_opt.force_keyframe = PJ_TRUE;
 
844
        stream->force_keyframe = PJ_FALSE;
 
845
        TRC_((channel->port.info.name.ptr,
 
846
              "Forcing encoder to generate keyframe"));
 
847
    }
 
848
 
 
849
    /* Encode! */
 
850
    status = pjmedia_vid_codec_encode_begin(stream->codec, &enc_opt, frame,
 
851
                                            channel->buf_size -
 
852
                                               sizeof(pjmedia_rtp_hdr),
 
853
                                            &frame_out,
 
854
                                            &has_more_data);
 
855
    if (status != PJ_SUCCESS) {
 
856
        LOGERR_((channel->port.info.name.ptr,
 
857
                "Codec encode_begin() error", status));
 
858
 
 
859
        /* Update RTP timestamp */
 
860
        pjmedia_rtp_encode_rtp(&channel->rtp, channel->pt, 1, 0,
 
861
                               rtp_ts_len,  (const void**)&rtphdr,
 
862
                               &rtphdrlen);
 
863
        return status;
 
864
    }
 
865
    
 
866
    pj_get_timestamp(&initial_time);
 
867
 
 
868
    /* Loop while we have frame to send */
 
869
    for (;;) {
 
870
        status = pjmedia_rtp_encode_rtp(&channel->rtp,
 
871
                                        channel->pt,
 
872
                                        (has_more_data == PJ_FALSE ? 1 : 0),
 
873
                                        (int)frame_out.size,
 
874
                                        rtp_ts_len,
 
875
                                        (const void**)&rtphdr,
 
876
                                        &rtphdrlen);
 
877
        if (status != PJ_SUCCESS) {
 
878
            LOGERR_((channel->port.info.name.ptr,
 
879
                    "RTP encode_rtp() error", status));
 
880
            return status;
 
881
        }
 
882
 
 
883
        // Copy RTP header to the beginning of packet
 
884
        pj_memcpy(channel->buf, rtphdr, sizeof(pjmedia_rtp_hdr));
 
885
 
 
886
        // Send the RTP packet to the transport.
 
887
        status = pjmedia_transport_send_rtp(stream->transport,
 
888
                                            (char*)channel->buf,
 
889
                                            frame_out.size +
 
890
                                                sizeof(pjmedia_rtp_hdr));
 
891
        if (status != PJ_SUCCESS) {
 
892
            enum { COUNT_TO_REPORT = 20 };
 
893
            if (stream->send_err_cnt++ == 0) {
 
894
                LOGERR_((channel->port.info.name.ptr,
 
895
                         "Transport send_rtp() error",
 
896
                         status));
 
897
            }
 
898
            if (stream->send_err_cnt > COUNT_TO_REPORT)
 
899
                stream->send_err_cnt = 0;
 
900
            /* Ignore this error */
 
901
        }
 
902
 
 
903
        pjmedia_rtcp_tx_rtp(&stream->rtcp, (unsigned)frame_out.size);
 
904
        total_sent += frame_out.size;
 
905
        pkt_cnt++;
 
906
 
 
907
        if (!has_more_data)
 
908
            break;
 
909
 
 
910
        /* Next packets use same timestamp */
 
911
        rtp_ts_len = 0;
 
912
 
 
913
        frame_out.size = 0;
 
914
 
 
915
        /* Encode more! */
 
916
        status = pjmedia_vid_codec_encode_more(stream->codec,
 
917
                                               channel->buf_size -
 
918
                                                   sizeof(pjmedia_rtp_hdr),
 
919
                                               &frame_out,
 
920
                                               &has_more_data);
 
921
        if (status != PJ_SUCCESS) {
 
922
            LOGERR_((channel->port.info.name.ptr,
 
923
                     "Codec encode_more() error", status));
 
924
            /* Ignore this error (?) */
 
925
            break;
 
926
        }
 
927
 
 
928
        /* Send rate control */
 
929
        if (stream->info.rc_cfg.method==PJMEDIA_VID_STREAM_RC_SIMPLE_BLOCKING)
 
930
        {
 
931
            pj_timestamp now, next_send_ts, total_send_ts;
 
932
 
 
933
            total_send_ts.u64 = total_sent * stream->ts_freq.u64 * 8 /
 
934
                                stream->info.rc_cfg.bandwidth;
 
935
            next_send_ts = initial_time;
 
936
            pj_add_timestamp(&next_send_ts, &total_send_ts);
 
937
 
 
938
            pj_get_timestamp(&now);
 
939
            if (pj_cmp_timestamp(&now, &next_send_ts) < 0) {
 
940
                unsigned ms_sleep;
 
941
                ms_sleep = pj_elapsed_msec(&now, &next_send_ts);
 
942
 
 
943
                if (ms_sleep > 10)
 
944
                    ms_sleep = 10;
 
945
 
 
946
                pj_thread_sleep(ms_sleep);
 
947
            }
 
948
        }
 
949
    }
 
950
 
 
951
#if TRACE_RC
 
952
    /* Trace log for rate control */
 
953
    {
 
954
        pj_timestamp end_time;
 
955
        unsigned total_sleep;
 
956
 
 
957
        pj_get_timestamp(&end_time);
 
958
        total_sleep = pj_elapsed_msec(&initial_time, &end_time);
 
959
        PJ_LOG(5, (stream->name.ptr, "total pkt=%d size=%d sleep=%d",
 
960
                   pkt_cnt, total_sent, total_sleep));
 
961
 
 
962
        if (stream->tx_start.u64 == 0)
 
963
            stream->tx_start = initial_time;
 
964
        stream->tx_end = end_time;
 
965
        stream->rc_total_pkt += pkt_cnt;
 
966
        stream->rc_total_sleep += total_sleep;
 
967
        stream->rc_total_img++;
 
968
    }
 
969
#endif
 
970
 
 
971
    /* Check if now is the time to transmit RTCP SR/RR report. 
 
972
     * We only do this when stream direction is not "decoding only", because
 
973
     * when it is, check_tx_rtcp() will be handled by get_frame().
 
974
     */
 
975
    if (stream->dir != PJMEDIA_DIR_DECODING) {
 
976
        check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts));
 
977
    }
 
978
 
 
979
    /* Do nothing if we have nothing to transmit */
 
980
    if (total_sent == 0) {
 
981
        return PJ_SUCCESS;
 
982
    }
 
983
 
 
984
    /* Update stat */
 
985
    stream->rtcp.stat.rtp_tx_last_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts);
 
986
    stream->rtcp.stat.rtp_tx_last_seq = pj_ntohs(stream->enc->rtp.out_hdr.seq);
 
987
 
 
988
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
 
989
    /* Update timestamp of last sending packet. */
 
990
    stream->last_frm_ts_sent = frame->timestamp;
 
991
#endif
 
992
 
 
993
    return PJ_SUCCESS;
 
994
}
 
995
 
 
996
/* Decode one image from jitter buffer */
 
997
static pj_status_t decode_frame(pjmedia_vid_stream *stream,
 
998
                                pjmedia_frame *frame)
 
999
{
 
1000
    pjmedia_vid_channel *channel = stream->dec;
 
1001
    pj_uint32_t last_ts = 0;
 
1002
    int frm_first_seq = 0, frm_last_seq = 0;
 
1003
    pj_bool_t got_frame = PJ_FALSE;
 
1004
    unsigned cnt;
 
1005
    pj_status_t status;
 
1006
 
 
1007
    /* Repeat get payload from the jitter buffer until all payloads with same
 
1008
     * timestamp are collected.
 
1009
     */
 
1010
 
 
1011
    /* Check if we got a decodable frame */
 
1012
    for (cnt=0; ; ++cnt) {
 
1013
        char ptype;
 
1014
        pj_uint32_t ts;
 
1015
        int seq;
 
1016
 
 
1017
        /* Peek frame from jitter buffer. */
 
1018
        pjmedia_jbuf_peek_frame(stream->jb, cnt, NULL, NULL,
 
1019
                                &ptype, NULL, &ts, &seq);
 
1020
        if (ptype == PJMEDIA_JB_NORMAL_FRAME) {
 
1021
            if (last_ts == 0) {
 
1022
                last_ts = ts;
 
1023
                frm_first_seq = seq;
 
1024
            }
 
1025
            if (ts != last_ts) {
 
1026
                got_frame = PJ_TRUE;
 
1027
                break;
 
1028
            }
 
1029
            frm_last_seq = seq;
 
1030
        } else if (ptype == PJMEDIA_JB_ZERO_EMPTY_FRAME) {
 
1031
            /* No more packet in the jitter buffer */
 
1032
            break;
 
1033
        }
 
1034
    }
 
1035
 
 
1036
    if (got_frame) {
 
1037
        unsigned i;
 
1038
 
 
1039
        /* Generate frame bitstream from the payload */
 
1040
        if (cnt > stream->rx_frame_cnt) {
 
1041
            PJ_LOG(1,(channel->port.info.name.ptr,
 
1042
                      "Discarding %u frames because array is full!",
 
1043
                      cnt - stream->rx_frame_cnt));
 
1044
            pjmedia_jbuf_remove_frame(stream->jb, cnt - stream->rx_frame_cnt);
 
1045
            cnt = stream->rx_frame_cnt;
 
1046
        }
 
1047
 
 
1048
        for (i = 0; i < cnt; ++i) {
 
1049
            char ptype;
 
1050
 
 
1051
            stream->rx_frames[i].type = PJMEDIA_FRAME_TYPE_VIDEO;
 
1052
            stream->rx_frames[i].timestamp.u64 = last_ts;
 
1053
            stream->rx_frames[i].bit_info = 0;
 
1054
 
 
1055
            /* We use jbuf_peek_frame() as it will returns the pointer of
 
1056
             * the payload (no buffer and memcpy needed), just as we need.
 
1057
             */
 
1058
            pjmedia_jbuf_peek_frame(stream->jb, i,
 
1059
                                    (const void**)&stream->rx_frames[i].buf,
 
1060
                                    &stream->rx_frames[i].size, &ptype,
 
1061
                                    NULL, NULL, NULL);
 
1062
 
 
1063
            if (ptype != PJMEDIA_JB_NORMAL_FRAME) {
 
1064
                /* Packet lost, must set payload to NULL and keep going */
 
1065
                stream->rx_frames[i].buf = NULL;
 
1066
                stream->rx_frames[i].size = 0;
 
1067
                stream->rx_frames[i].type = PJMEDIA_FRAME_TYPE_NONE;
 
1068
                continue;
 
1069
            }
 
1070
        }
 
1071
 
 
1072
        /* Decode */
 
1073
        status = pjmedia_vid_codec_decode(stream->codec, cnt,
 
1074
                                          stream->rx_frames,
 
1075
                                          (unsigned)frame->size, frame);
 
1076
        if (status != PJ_SUCCESS) {
 
1077
            LOGERR_((channel->port.info.name.ptr, "codec decode() error",
 
1078
                     status));
 
1079
            frame->type = PJMEDIA_FRAME_TYPE_NONE;
 
1080
            frame->size = 0;
 
1081
        }
 
1082
 
 
1083
        pjmedia_jbuf_remove_frame(stream->jb, cnt);
 
1084
    }
 
1085
 
 
1086
    /* Learn remote frame rate after successful decoding */
 
1087
    if (frame->type == PJMEDIA_FRAME_TYPE_VIDEO && frame->size)
 
1088
    {
 
1089
        /* Only check remote frame rate when timestamp is not wrapping and
 
1090
         * sequence is increased by 1.
 
1091
         */
 
1092
        if (last_ts > stream->last_dec_ts &&
 
1093
            frm_first_seq - stream->last_dec_seq == 1)
 
1094
        {
 
1095
            pj_uint32_t ts_diff;
 
1096
            pjmedia_video_format_detail *vfd;
 
1097
 
 
1098
            ts_diff = last_ts - stream->last_dec_ts;
 
1099
            vfd = pjmedia_format_get_video_format_detail(
 
1100
                                    &channel->port.info.fmt, PJ_TRUE);
 
1101
            if (stream->info.codec_info.clock_rate * vfd->fps.denum !=
 
1102
                vfd->fps.num * ts_diff)
 
1103
            {
 
1104
                /* Frame rate changed, update decoding port info */
 
1105
                if (stream->info.codec_info.clock_rate % ts_diff == 0) {
 
1106
                    vfd->fps.num = stream->info.codec_info.clock_rate/ts_diff;
 
1107
                    vfd->fps.denum = 1;
 
1108
                } else {
 
1109
                    vfd->fps.num = stream->info.codec_info.clock_rate;
 
1110
                    vfd->fps.denum = ts_diff;
 
1111
                }
 
1112
 
 
1113
                /* Update stream info */
 
1114
                stream->info.codec_param->dec_fmt.det.vid.fps = vfd->fps;
 
1115
 
 
1116
                /* Publish PJMEDIA_EVENT_FMT_CHANGED event if frame rate
 
1117
                 * increased and not exceeding 100fps.
 
1118
                 */
 
1119
                if (vfd->fps.num/vfd->fps.denum <= 100 &&
 
1120
                    vfd->fps.num * stream->dec_max_fps.denum >
 
1121
                    stream->dec_max_fps.num * vfd->fps.denum)
 
1122
                {
 
1123
                    pjmedia_event *event = &stream->fmt_event;
 
1124
 
 
1125
                    /* Update max fps of decoding dir */
 
1126
                    stream->dec_max_fps = vfd->fps;
 
1127
 
 
1128
                    /* Use the buffered format changed event:
 
1129
                     * - just update the framerate if there is pending event,
 
1130
                     * - otherwise, init the whole event.
 
1131
                     */
 
1132
                    if (stream->fmt_event.type != PJMEDIA_EVENT_NONE) {
 
1133
                        event->data.fmt_changed.new_fmt.det.vid.fps = vfd->fps;
 
1134
                    } else {
 
1135
                        pjmedia_event_init(event, PJMEDIA_EVENT_FMT_CHANGED,
 
1136
                                           &frame->timestamp, stream);
 
1137
                        event->data.fmt_changed.dir = PJMEDIA_DIR_DECODING;
 
1138
                        pj_memcpy(&event->data.fmt_changed.new_fmt,
 
1139
                                  &stream->info.codec_param->dec_fmt,
 
1140
                                  sizeof(pjmedia_format));
 
1141
                    }
 
1142
                }
 
1143
            }
 
1144
        }
 
1145
 
 
1146
        /* Update last frame seq and timestamp */
 
1147
        stream->last_dec_seq = frm_last_seq;
 
1148
        stream->last_dec_ts = last_ts;
 
1149
    }
 
1150
 
 
1151
    return got_frame ? PJ_SUCCESS : PJ_ENOTFOUND;
 
1152
}
 
1153
 
 
1154
 
 
1155
static pj_status_t get_frame(pjmedia_port *port,
 
1156
                             pjmedia_frame *frame)
 
1157
{
 
1158
    pjmedia_vid_stream *stream = (pjmedia_vid_stream*) port->port_data.pdata;
 
1159
    pjmedia_vid_channel *channel = stream->dec;
 
1160
 
 
1161
    /* Return no frame is channel is paused */
 
1162
    if (channel->paused) {
 
1163
        frame->type = PJMEDIA_FRAME_TYPE_NONE;
 
1164
        frame->size = 0;
 
1165
        return PJ_SUCCESS;
 
1166
    }
 
1167
 
 
1168
    /* Report pending events. Do not publish the event while holding the
 
1169
     * jb_mutex as that would lead to deadlock. It should be safe to
 
1170
     * operate on fmt_event without the mutex because format change normally
 
1171
     * would only occur once during the start of the media.
 
1172
     */
 
1173
    if (stream->fmt_event.type != PJMEDIA_EVENT_NONE) {
 
1174
        pjmedia_event_fmt_changed_data *fmt_chg_data;
 
1175
 
 
1176
        fmt_chg_data = &stream->fmt_event.data.fmt_changed;
 
1177
 
 
1178
        /* Update stream info and decoding channel port info */
 
1179
        if (fmt_chg_data->dir == PJMEDIA_DIR_DECODING) {
 
1180
            pjmedia_format_copy(&stream->info.codec_param->dec_fmt,
 
1181
                                &fmt_chg_data->new_fmt);
 
1182
            pjmedia_format_copy(&stream->dec->port.info.fmt,
 
1183
                                &fmt_chg_data->new_fmt);
 
1184
 
 
1185
            /* Override the framerate to be 1.5x higher in the event
 
1186
             * for the renderer.
 
1187
             */
 
1188
            fmt_chg_data->new_fmt.det.vid.fps.num *= 3;
 
1189
            fmt_chg_data->new_fmt.det.vid.fps.num /= 2;
 
1190
        } else {
 
1191
            pjmedia_format_copy(&stream->info.codec_param->enc_fmt,
 
1192
                                &fmt_chg_data->new_fmt);
 
1193
            pjmedia_format_copy(&stream->enc->port.info.fmt,
 
1194
                                &fmt_chg_data->new_fmt);
 
1195
        }
 
1196
 
 
1197
        dump_port_info(fmt_chg_data->dir==PJMEDIA_DIR_DECODING ?
 
1198
                        stream->dec : stream->enc,
 
1199
                       "changed");
 
1200
 
 
1201
        pjmedia_event_publish(NULL, port, &stream->fmt_event, 0);
 
1202
 
 
1203
        stream->fmt_event.type = PJMEDIA_EVENT_NONE;
 
1204
    }
 
1205
 
 
1206
    if (stream->miss_keyframe_event.type != PJMEDIA_EVENT_NONE) {
 
1207
        pjmedia_event_publish(NULL, port, &stream->miss_keyframe_event,
 
1208
                              PJMEDIA_EVENT_PUBLISH_POST_EVENT);
 
1209
        stream->miss_keyframe_event.type = PJMEDIA_EVENT_NONE;
 
1210
    }
 
1211
 
 
1212
    pj_mutex_lock( stream->jb_mutex );
 
1213
 
 
1214
    if (stream->dec_frame.size == 0) {
 
1215
        /* Don't have frame in buffer, try to decode one */
 
1216
        if (decode_frame(stream, frame) != PJ_SUCCESS) {
 
1217
            frame->type = PJMEDIA_FRAME_TYPE_NONE;
 
1218
            frame->size = 0;
 
1219
        }
 
1220
    } else {
 
1221
        if (frame->size < stream->dec_frame.size) {
 
1222
            PJ_LOG(4,(stream->dec->port.info.name.ptr,
 
1223
                      "Error: not enough buffer for decoded frame "
 
1224
                      "(supplied=%d, required=%d)",
 
1225
                      (int)frame->size, (int)stream->dec_frame.size));
 
1226
            frame->type = PJMEDIA_FRAME_TYPE_NONE;
 
1227
            frame->size = 0;
 
1228
        } else {
 
1229
            frame->type = stream->dec_frame.type;
 
1230
            frame->timestamp = stream->dec_frame.timestamp;
 
1231
            frame->size = stream->dec_frame.size;
 
1232
            pj_memcpy(frame->buf, stream->dec_frame.buf, frame->size);
 
1233
        }
 
1234
 
 
1235
        stream->dec_frame.size = 0;
 
1236
    }
 
1237
 
 
1238
    pj_mutex_unlock( stream->jb_mutex );
 
1239
 
 
1240
    return PJ_SUCCESS;
 
1241
}
 
1242
 
 
1243
/*
 
1244
 * Create media channel.
 
1245
 */
 
1246
static pj_status_t create_channel( pj_pool_t *pool,
 
1247
                                   pjmedia_vid_stream *stream,
 
1248
                                   pjmedia_dir dir,
 
1249
                                   unsigned pt,
 
1250
                                   const pjmedia_vid_stream_info *info,
 
1251
                                   pjmedia_vid_channel **p_channel)
 
1252
{
 
1253
    enum { M = 32 };
 
1254
    pjmedia_vid_channel *channel;
 
1255
    pj_status_t status;
 
1256
    unsigned min_out_pkt_size;
 
1257
    pj_str_t name;
 
1258
    const char *type_name;
 
1259
    pjmedia_format *fmt;
 
1260
    char fourcc_name[5];
 
1261
    pjmedia_port_info *pi;
 
1262
    
 
1263
    pj_assert(info->type == PJMEDIA_TYPE_VIDEO);
 
1264
    pj_assert(dir == PJMEDIA_DIR_DECODING || dir == PJMEDIA_DIR_ENCODING);
 
1265
 
 
1266
    /* Allocate memory for channel descriptor */
 
1267
    channel = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_channel);
 
1268
    PJ_ASSERT_RETURN(channel != NULL, PJ_ENOMEM);
 
1269
 
 
1270
    /* Init vars */
 
1271
    if (dir==PJMEDIA_DIR_DECODING) {
 
1272
        type_name = "vstdec";
 
1273
        fmt = &info->codec_param->dec_fmt;
 
1274
    } else {
 
1275
        type_name = "vstenc";
 
1276
        fmt = &info->codec_param->enc_fmt;
 
1277
    }
 
1278
    name.ptr = (char*) pj_pool_alloc(pool, M);
 
1279
    name.slen = pj_ansi_snprintf(name.ptr, M, "%s%p", type_name, stream);
 
1280
    pi = &channel->port.info;
 
1281
 
 
1282
    /* Init channel info. */
 
1283
    channel->stream = stream;
 
1284
    channel->dir = dir;
 
1285
    channel->paused = 1;
 
1286
    channel->pt = pt;
 
1287
    
 
1288
    /* Allocate buffer for outgoing packet. */
 
1289
    if (dir == PJMEDIA_DIR_ENCODING) {
 
1290
        channel->buf_size = sizeof(pjmedia_rtp_hdr) + stream->frame_size;
 
1291
 
 
1292
        /* It should big enough to hold (minimally) RTCP SR with an SDES. */
 
1293
        min_out_pkt_size =  sizeof(pjmedia_rtcp_sr_pkt) +
 
1294
                            sizeof(pjmedia_rtcp_common) +
 
1295
                            (4 + (unsigned)stream->cname.slen) +
 
1296
                            32;
 
1297
 
 
1298
        if (channel->buf_size < min_out_pkt_size)
 
1299
            channel->buf_size = min_out_pkt_size;
 
1300
 
 
1301
        channel->buf = pj_pool_alloc(pool, channel->buf_size);
 
1302
        PJ_ASSERT_RETURN(channel->buf != NULL, PJ_ENOMEM);
 
1303
    }
 
1304
 
 
1305
    /* Create RTP and RTCP sessions: */
 
1306
    if (info->rtp_seq_ts_set == 0) {
 
1307
        status = pjmedia_rtp_session_init(&channel->rtp, pt, info->ssrc);
 
1308
    } else {
 
1309
        pjmedia_rtp_session_setting settings;
 
1310
 
 
1311
        settings.flags = (pj_uint8_t)((info->rtp_seq_ts_set << 2) | 3);
 
1312
        settings.default_pt = pt;
 
1313
        settings.sender_ssrc = info->ssrc;
 
1314
        settings.seq = info->rtp_seq;
 
1315
        settings.ts = info->rtp_ts;
 
1316
        status = pjmedia_rtp_session_init2(&channel->rtp, settings);
 
1317
    }
 
1318
    if (status != PJ_SUCCESS)
 
1319
        return status;
 
1320
 
 
1321
    /* Init port. */
 
1322
    pjmedia_port_info_init2(pi, &name, SIGNATURE, dir, fmt);
 
1323
    if (dir == PJMEDIA_DIR_DECODING) {
 
1324
        channel->port.get_frame = &get_frame;
 
1325
    } else {
 
1326
        pi->fmt.id = info->codec_param->dec_fmt.id;
 
1327
        channel->port.put_frame = &put_frame;
 
1328
    }
 
1329
 
 
1330
    /* Init port. */
 
1331
    channel->port.port_data.pdata = stream;
 
1332
 
 
1333
    PJ_LOG(5, (name.ptr,
 
1334
               "%s channel created %dx%d %s%s%.*s %d/%d(~%d)fps",
 
1335
               (dir==PJMEDIA_DIR_ENCODING?"Encoding":"Decoding"),
 
1336
               pi->fmt.det.vid.size.w, pi->fmt.det.vid.size.h,
 
1337
               pjmedia_fourcc_name(pi->fmt.id, fourcc_name),
 
1338
               (dir==PJMEDIA_DIR_ENCODING?"->":"<-"),
 
1339
               info->codec_info.encoding_name.slen,
 
1340
               info->codec_info.encoding_name.ptr,
 
1341
               pi->fmt.det.vid.fps.num, pi->fmt.det.vid.fps.denum,
 
1342
               pi->fmt.det.vid.fps.num/pi->fmt.det.vid.fps.denum));
 
1343
 
 
1344
    /* Done. */
 
1345
    *p_channel = channel;
 
1346
    return PJ_SUCCESS;
 
1347
}
 
1348
 
 
1349
 
 
1350
/*
 
1351
 * Create stream.
 
1352
 */
 
1353
PJ_DEF(pj_status_t) pjmedia_vid_stream_create(
 
1354
                                        pjmedia_endpt *endpt,
 
1355
                                        pj_pool_t *pool,
 
1356
                                        pjmedia_vid_stream_info *info,
 
1357
                                        pjmedia_transport *tp,
 
1358
                                        void *user_data,
 
1359
                                        pjmedia_vid_stream **p_stream)
 
1360
{
 
1361
    enum { M = 32 };
 
1362
    pj_pool_t *own_pool = NULL;
 
1363
    pjmedia_vid_stream *stream;
 
1364
    unsigned jb_init, jb_max, jb_min_pre, jb_max_pre;
 
1365
    int frm_ptime, chunks_per_frm;
 
1366
    pjmedia_video_format_detail *vfd_enc, *vfd_dec;
 
1367
    char *p;
 
1368
    pj_status_t status;
 
1369
 
 
1370
    if (!pool) {
 
1371
        own_pool = pjmedia_endpt_create_pool( endpt, "vstrm%p",
 
1372
                                              PJMEDIA_VSTREAM_SIZE,
 
1373
                                              PJMEDIA_VSTREAM_INC);
 
1374
        PJ_ASSERT_RETURN(own_pool != NULL, PJ_ENOMEM);
 
1375
        pool = own_pool;
 
1376
    }
 
1377
 
 
1378
    /* Allocate stream */
 
1379
    stream = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_stream);
 
1380
    PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM);
 
1381
    stream->own_pool = own_pool;
 
1382
 
 
1383
    /* Get codec manager */
 
1384
    stream->codec_mgr = pjmedia_vid_codec_mgr_instance();
 
1385
    PJ_ASSERT_RETURN(stream->codec_mgr, PJMEDIA_CODEC_EFAILED);
 
1386
 
 
1387
    /* Init stream/port name */
 
1388
    stream->name.ptr = (char*) pj_pool_alloc(pool, M);
 
1389
    stream->name.slen = pj_ansi_snprintf(stream->name.ptr, M, 
 
1390
                                         "vstrm%p", stream);
 
1391
 
 
1392
    /* Create and initialize codec: */
 
1393
    status = pjmedia_vid_codec_mgr_alloc_codec(stream->codec_mgr, 
 
1394
                                               &info->codec_info,
 
1395
                                               &stream->codec);
 
1396
    if (status != PJ_SUCCESS)
 
1397
        return status;
 
1398
 
 
1399
    /* Get codec param: */
 
1400
    if (!info->codec_param) {
 
1401
        pjmedia_vid_codec_param def_param;
 
1402
 
 
1403
        status = pjmedia_vid_codec_mgr_get_default_param(stream->codec_mgr, 
 
1404
                                                         &info->codec_info,
 
1405
                                                         &def_param);
 
1406
        if (status != PJ_SUCCESS)
 
1407
            return status;
 
1408
 
 
1409
        info->codec_param = pjmedia_vid_codec_param_clone(pool, &def_param);
 
1410
        pj_assert(info->codec_param);
 
1411
    }
 
1412
 
 
1413
    /* Init codec param and adjust MTU */
 
1414
    info->codec_param->dir = info->dir;
 
1415
    info->codec_param->enc_mtu -= (sizeof(pjmedia_rtp_hdr) +
 
1416
                                   PJMEDIA_STREAM_RESV_PAYLOAD_LEN);
 
1417
    if (info->codec_param->enc_mtu > PJMEDIA_MAX_MTU)
 
1418
        info->codec_param->enc_mtu = PJMEDIA_MAX_MTU;
 
1419
 
 
1420
    /* Packet size estimation for decoding direction */
 
1421
    vfd_enc = pjmedia_format_get_video_format_detail(
 
1422
                                        &info->codec_param->enc_fmt, PJ_TRUE);
 
1423
    vfd_dec = pjmedia_format_get_video_format_detail(
 
1424
                                        &info->codec_param->dec_fmt, PJ_TRUE);
 
1425
 
 
1426
    /* Init stream: */
 
1427
    stream->endpt = endpt;
 
1428
    stream->dir = info->dir;
 
1429
    stream->user_data = user_data;
 
1430
    stream->rtcp_interval = (PJMEDIA_RTCP_INTERVAL-500 + (pj_rand()%1000)) *
 
1431
                            info->codec_info.clock_rate / 1000;
 
1432
    stream->rtcp_sdes_bye_disabled = info->rtcp_sdes_bye_disabled;
 
1433
 
 
1434
    stream->jb_last_frm = PJMEDIA_JB_NORMAL_FRAME;
 
1435
 
 
1436
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
 
1437
    stream->use_ka = info->use_ka;
 
1438
#endif
 
1439
 
 
1440
    /* Build random RTCP CNAME. CNAME has user@host format */
 
1441
    stream->cname.ptr = p = (char*) pj_pool_alloc(pool, 20);
 
1442
    pj_create_random_string(p, 5);
 
1443
    p += 5;
 
1444
    *p++ = '@'; *p++ = 'p'; *p++ = 'j';
 
1445
    pj_create_random_string(p, 6);
 
1446
    p += 6;
 
1447
    *p++ = '.'; *p++ = 'o'; *p++ = 'r'; *p++ = 'g';
 
1448
    stream->cname.slen = p - stream->cname.ptr;
 
1449
 
 
1450
 
 
1451
    /* Create mutex to protect jitter buffer: */
 
1452
 
 
1453
    status = pj_mutex_create_simple(pool, NULL, &stream->jb_mutex);
 
1454
    if (status != PJ_SUCCESS)
 
1455
        return status;
 
1456
 
 
1457
    /* Init and open the codec. */
 
1458
    status = pjmedia_vid_codec_init(stream->codec, pool);
 
1459
    if (status != PJ_SUCCESS)
 
1460
        return status;
 
1461
    status = pjmedia_vid_codec_open(stream->codec, info->codec_param);
 
1462
    if (status != PJ_SUCCESS)
 
1463
        return status;
 
1464
 
 
1465
    /* Subscribe to codec events */
 
1466
    pjmedia_event_subscribe(NULL, &stream_event_cb, stream,
 
1467
                            stream->codec);
 
1468
 
 
1469
    /* Estimate the maximum frame size */
 
1470
    stream->frame_size = vfd_enc->size.w * vfd_enc->size.h * 4;
 
1471
 
 
1472
#if 0
 
1473
    stream->frame_size = vfd_enc->max_bps/8 * vfd_enc->fps.denum /
 
1474
                         vfd_enc->fps.num;
 
1475
    
 
1476
    /* As the maximum frame_size is not represented directly by maximum bps
 
1477
     * (which includes intra and predicted frames), let's increase the
 
1478
     * frame size value for safety.
 
1479
     */
 
1480
    stream->frame_size <<= 4;
 
1481
#endif
 
1482
 
 
1483
    /* Validate the frame size */
 
1484
    if (stream->frame_size == 0 || 
 
1485
        stream->frame_size > PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE)
 
1486
    {
 
1487
        stream->frame_size = PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE;
 
1488
    }
 
1489
 
 
1490
    /* Get frame length in timestamp unit */
 
1491
    stream->frame_ts_len = info->codec_info.clock_rate *
 
1492
                           vfd_enc->fps.denum / vfd_enc->fps.num;
 
1493
 
 
1494
    /* Initialize send rate states */
 
1495
    pj_get_timestamp_freq(&stream->ts_freq);
 
1496
    if (info->rc_cfg.bandwidth == 0)
 
1497
        info->rc_cfg.bandwidth = vfd_enc->max_bps;
 
1498
 
 
1499
    /* For simple blocking, need to have bandwidth large enough, otherwise
 
1500
     * we can slow down the transmission too much
 
1501
     */
 
1502
    if (info->rc_cfg.method==PJMEDIA_VID_STREAM_RC_SIMPLE_BLOCKING &&
 
1503
        info->rc_cfg.bandwidth < vfd_enc->avg_bps * 3)
 
1504
    {
 
1505
        info->rc_cfg.bandwidth = vfd_enc->avg_bps * 3;
 
1506
    }
 
1507
 
 
1508
    /* Override the initial framerate in the decoding direction. This initial
 
1509
     * value will be used by the renderer to configure its clock, and setting
 
1510
     * it to a bit higher value can avoid the possibility of high latency
 
1511
     * caused by clock drift (remote encoder clock runs slightly faster than
 
1512
     * local renderer clock) or video setup lag. Note that the actual framerate
 
1513
     * will be continuously calculated based on the incoming RTP timestamps.
 
1514
     */
 
1515
    vfd_dec->fps.num = vfd_dec->fps.num * 3 / 2;
 
1516
    stream->dec_max_fps = vfd_dec->fps;
 
1517
 
 
1518
    /* Create decoder channel */
 
1519
    status = create_channel( pool, stream, PJMEDIA_DIR_DECODING, 
 
1520
                             info->rx_pt, info, &stream->dec);
 
1521
    if (status != PJ_SUCCESS)
 
1522
        return status;
 
1523
 
 
1524
    /* Create encoder channel */
 
1525
    status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING, 
 
1526
                             info->tx_pt, info, &stream->enc);
 
1527
    if (status != PJ_SUCCESS)
 
1528
        return status;
 
1529
 
 
1530
    /* Create temporary buffer for immediate decoding */
 
1531
    stream->dec_max_size = vfd_dec->size.w * vfd_dec->size.h * 4;
 
1532
    stream->dec_frame.buf = pj_pool_alloc(pool, stream->dec_max_size);
 
1533
 
 
1534
    /* Init jitter buffer parameters: */
 
1535
    frm_ptime       = 1000 * vfd_enc->fps.denum / vfd_enc->fps.num;
 
1536
    chunks_per_frm  = stream->frame_size / PJMEDIA_MAX_MRU;
 
1537
    if (chunks_per_frm < MIN_CHUNKS_PER_FRM)
 
1538
        chunks_per_frm = MIN_CHUNKS_PER_FRM;
 
1539
 
 
1540
    /* JB max count, default 500ms */
 
1541
    if (info->jb_max >= frm_ptime)
 
1542
        jb_max      = info->jb_max * chunks_per_frm / frm_ptime;
 
1543
    else
 
1544
        jb_max      = 500 * chunks_per_frm / frm_ptime;
 
1545
 
 
1546
    /* JB min prefetch, default 1 frame */
 
1547
    if (info->jb_min_pre >= frm_ptime)
 
1548
        jb_min_pre  = info->jb_min_pre * chunks_per_frm / frm_ptime;
 
1549
    else
 
1550
        jb_min_pre  = 1;
 
1551
 
 
1552
    /* JB max prefetch, default 4/5 JB max count */
 
1553
    if (info->jb_max_pre >= frm_ptime)
 
1554
        jb_max_pre  = info->jb_max_pre * chunks_per_frm / frm_ptime;
 
1555
    else
 
1556
        jb_max_pre  = jb_max * 4 / 5;
 
1557
 
 
1558
    /* JB init prefetch, default 0 */
 
1559
    if (info->jb_init >= frm_ptime)
 
1560
        jb_init  = info->jb_init * chunks_per_frm / frm_ptime;
 
1561
    else
 
1562
        jb_init  = 0;
 
1563
 
 
1564
    /* Allocate array for temporary storage for assembly of incoming
 
1565
     * frames. Add more just in case.
 
1566
     */
 
1567
    stream->rx_frame_cnt = chunks_per_frm * 2;
 
1568
    stream->rx_frames = pj_pool_calloc(pool, stream->rx_frame_cnt,
 
1569
                                       sizeof(stream->rx_frames[0]));
 
1570
 
 
1571
    /* Create jitter buffer */
 
1572
    status = pjmedia_jbuf_create(pool, &stream->dec->port.info.name,
 
1573
                                 PJMEDIA_MAX_MRU,
 
1574
                                 1000 * vfd_enc->fps.denum / vfd_enc->fps.num,
 
1575
                                 jb_max, &stream->jb);
 
1576
    if (status != PJ_SUCCESS)
 
1577
        return status;
 
1578
 
 
1579
 
 
1580
    /* Set up jitter buffer */
 
1581
    pjmedia_jbuf_set_adaptive(stream->jb, jb_init, jb_min_pre, jb_max_pre);
 
1582
    pjmedia_jbuf_set_discard(stream->jb, PJMEDIA_JB_DISCARD_NONE);
 
1583
 
 
1584
    /* Init RTCP session: */
 
1585
    {
 
1586
        pjmedia_rtcp_session_setting rtcp_setting;
 
1587
 
 
1588
        pjmedia_rtcp_session_setting_default(&rtcp_setting);
 
1589
        rtcp_setting.name = stream->name.ptr;
 
1590
        rtcp_setting.ssrc = info->ssrc;
 
1591
        rtcp_setting.rtp_ts_base = pj_ntohl(stream->enc->rtp.out_hdr.ts);
 
1592
        rtcp_setting.clock_rate = info->codec_info.clock_rate;
 
1593
        rtcp_setting.samples_per_frame = 1;
 
1594
 
 
1595
        pjmedia_rtcp_init2(&stream->rtcp, &rtcp_setting);
 
1596
    }
 
1597
 
 
1598
    /* Allocate outgoing RTCP buffer, should be enough to hold SR/RR, SDES,
 
1599
     * BYE, and XR.
 
1600
     */
 
1601
    stream->out_rtcp_pkt_size =  sizeof(pjmedia_rtcp_sr_pkt) +
 
1602
                                 sizeof(pjmedia_rtcp_common) +
 
1603
                                 (4 + (unsigned)stream->cname.slen) +
 
1604
                                 32;
 
1605
    if (stream->out_rtcp_pkt_size > PJMEDIA_MAX_MTU)
 
1606
        stream->out_rtcp_pkt_size = PJMEDIA_MAX_MTU;
 
1607
 
 
1608
    stream->out_rtcp_pkt = pj_pool_alloc(pool, stream->out_rtcp_pkt_size);
 
1609
 
 
1610
    /* Only attach transport when stream is ready. */
 
1611
    status = pjmedia_transport_attach(tp, stream, &info->rem_addr, 
 
1612
                                      &info->rem_rtcp, 
 
1613
                                      pj_sockaddr_get_len(&info->rem_addr), 
 
1614
                                      &on_rx_rtp, &on_rx_rtcp);
 
1615
    if (status != PJ_SUCCESS)
 
1616
        return status;
 
1617
 
 
1618
    stream->transport = tp;
 
1619
 
 
1620
    /* Send RTCP SDES */
 
1621
    if (!stream->rtcp_sdes_bye_disabled) {
 
1622
        pjmedia_vid_stream_send_rtcp_sdes(stream);
 
1623
    }
 
1624
 
 
1625
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
 
1626
    /* NAT hole punching by sending KA packet via RTP transport. */
 
1627
    if (stream->use_ka)
 
1628
        send_keep_alive_packet(stream);
 
1629
#endif
 
1630
 
 
1631
#if TRACE_JB
 
1632
    {
 
1633
        char trace_name[PJ_MAXPATH];
 
1634
        pj_ssize_t len;
 
1635
 
 
1636
        pj_ansi_snprintf(trace_name, sizeof(trace_name), 
 
1637
                         TRACE_JB_PATH_PREFIX "%s.csv",
 
1638
                         channel->port.info.name.ptr);
 
1639
        status = pj_file_open(pool, trace_name, PJ_O_RDWR,
 
1640
                              &stream->trace_jb_fd);
 
1641
        if (status != PJ_SUCCESS) {
 
1642
            stream->trace_jb_fd = TRACE_JB_INVALID_FD;
 
1643
            PJ_LOG(3,(THIS_FILE, "Failed creating RTP trace file '%s'", 
 
1644
                      trace_name));
 
1645
        } else {
 
1646
            stream->trace_jb_buf = (char*)pj_pool_alloc(pool, PJ_LOG_MAX_SIZE);
 
1647
 
 
1648
            /* Print column header */
 
1649
            len = pj_ansi_snprintf(stream->trace_jb_buf, PJ_LOG_MAX_SIZE,
 
1650
                                   "Time, Operation, Size, Frame Count, "
 
1651
                                   "Frame type, RTP Seq, RTP TS, RTP M, "
 
1652
                                   "JB size, JB burst level, JB prefetch\n");
 
1653
            if (len < 1 || len >= PJ_LOG_MAX_SIZE)
 
1654
                len = PJ_LOG_MAX_SIZE - 1;
 
1655
            pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len);
 
1656
            pj_file_flush(stream->trace_jb_fd);
 
1657
        }
 
1658
    }
 
1659
#endif
 
1660
 
 
1661
    /* Save the stream info */
 
1662
    pj_memcpy(&stream->info, info, sizeof(*info));
 
1663
    stream->info.codec_param = pjmedia_vid_codec_param_clone(
 
1664
                                                pool, info->codec_param);
 
1665
 
 
1666
    /* Success! */
 
1667
    *p_stream = stream;
 
1668
 
 
1669
    PJ_LOG(5,(THIS_FILE, "Video stream %s created", stream->name.ptr));
 
1670
 
 
1671
    return PJ_SUCCESS;
 
1672
}
 
1673
 
 
1674
 
 
1675
/*
 
1676
 * Destroy stream.
 
1677
 */
 
1678
PJ_DEF(pj_status_t) pjmedia_vid_stream_destroy( pjmedia_vid_stream *stream )
 
1679
{
 
1680
    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
 
1681
 
 
1682
#if TRACE_RC
 
1683
    {
 
1684
        unsigned total_time;
 
1685
 
 
1686
        total_time = pj_elapsed_msec(&stream->tx_start, &stream->tx_end);
 
1687
        PJ_LOG(5, (stream->name.ptr, 
 
1688
                   "RC stat: pkt_cnt=%.2f/image, sleep=%.2fms/s, fps=%.2f",
 
1689
                   stream->rc_total_pkt*1.0/stream->rc_total_img,
 
1690
                   stream->rc_total_sleep*1000.0/total_time,
 
1691
                   stream->rc_total_img*1000.0/total_time));
 
1692
    }
 
1693
#endif
 
1694
 
 
1695
    /* Send RTCP BYE (also SDES) */
 
1696
    if (!stream->rtcp_sdes_bye_disabled) {
 
1697
        send_rtcp(stream, PJ_TRUE, PJ_TRUE);
 
1698
    }
 
1699
 
 
1700
    /* Detach from transport 
 
1701
     * MUST NOT hold stream mutex while detaching from transport, as
 
1702
     * it may cause deadlock. See ticket #460 for the details.
 
1703
     */
 
1704
    if (stream->transport) {
 
1705
        pjmedia_transport_detach(stream->transport, stream);
 
1706
        stream->transport = NULL;
 
1707
    }
 
1708
 
 
1709
    /* This function may be called when stream is partly initialized. */
 
1710
    if (stream->jb_mutex)
 
1711
        pj_mutex_lock(stream->jb_mutex);
 
1712
 
 
1713
 
 
1714
    /* Free codec. */
 
1715
    if (stream->codec) {
 
1716
        pjmedia_event_unsubscribe(NULL, &stream_event_cb, stream,
 
1717
                                  stream->codec);
 
1718
        pjmedia_vid_codec_close(stream->codec);
 
1719
        pjmedia_vid_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec);
 
1720
        stream->codec = NULL;
 
1721
    }
 
1722
 
 
1723
    /* Free mutex */
 
1724
    
 
1725
    if (stream->jb_mutex) {
 
1726
        pj_mutex_destroy(stream->jb_mutex);
 
1727
        stream->jb_mutex = NULL;
 
1728
    }
 
1729
 
 
1730
    /* Destroy jitter buffer */
 
1731
    if (stream->jb) {
 
1732
        pjmedia_jbuf_destroy(stream->jb);
 
1733
        stream->jb = NULL;
 
1734
    }
 
1735
 
 
1736
#if TRACE_JB
 
1737
    if (TRACE_JB_OPENED(stream)) {
 
1738
        pj_file_close(stream->trace_jb_fd);
 
1739
        stream->trace_jb_fd = TRACE_JB_INVALID_FD;
 
1740
    }
 
1741
#endif
 
1742
 
 
1743
    if (stream->own_pool) {
 
1744
        pj_pool_t *pool = stream->own_pool;
 
1745
        stream->own_pool = NULL;
 
1746
        pj_pool_release(pool);
 
1747
    }
 
1748
 
 
1749
    return PJ_SUCCESS;
 
1750
}
 
1751
 
 
1752
 
 
1753
/*
 
1754
 * Get the port interface.
 
1755
 */
 
1756
PJ_DEF(pj_status_t) pjmedia_vid_stream_get_port(pjmedia_vid_stream *stream,
 
1757
                                                pjmedia_dir dir,
 
1758
                                                pjmedia_port **p_port )
 
1759
{
 
1760
    PJ_ASSERT_RETURN(dir==PJMEDIA_DIR_ENCODING || dir==PJMEDIA_DIR_DECODING,
 
1761
                     PJ_EINVAL);
 
1762
 
 
1763
    if (dir == PJMEDIA_DIR_ENCODING)
 
1764
        *p_port = &stream->enc->port;
 
1765
    else
 
1766
        *p_port = &stream->dec->port;
 
1767
 
 
1768
    return PJ_SUCCESS;
 
1769
}
 
1770
 
 
1771
 
 
1772
/*
 
1773
 * Get the transport object
 
1774
 */
 
1775
PJ_DEF(pjmedia_transport*) pjmedia_vid_stream_get_transport(
 
1776
                                                    pjmedia_vid_stream *st)
 
1777
{
 
1778
    return st->transport;
 
1779
}
 
1780
 
 
1781
 
 
1782
/*
 
1783
 * Get stream statistics.
 
1784
 */
 
1785
PJ_DEF(pj_status_t) pjmedia_vid_stream_get_stat(
 
1786
                                            const pjmedia_vid_stream *stream,
 
1787
                                            pjmedia_rtcp_stat *stat)
 
1788
{
 
1789
    PJ_ASSERT_RETURN(stream && stat, PJ_EINVAL);
 
1790
 
 
1791
    pj_memcpy(stat, &stream->rtcp.stat, sizeof(pjmedia_rtcp_stat));
 
1792
    return PJ_SUCCESS;
 
1793
}
 
1794
 
 
1795
 
 
1796
/*
 
1797
 * Reset the stream statistics in the middle of a stream session.
 
1798
 */
 
1799
PJ_DEF(pj_status_t) pjmedia_vid_stream_reset_stat(pjmedia_vid_stream *stream)
 
1800
{
 
1801
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
 
1802
 
 
1803
    pjmedia_rtcp_init_stat(&stream->rtcp.stat);
 
1804
 
 
1805
    return PJ_SUCCESS;
 
1806
}
 
1807
 
 
1808
 
 
1809
/*
 
1810
 * Get jitter buffer state.
 
1811
 */
 
1812
PJ_DEF(pj_status_t) pjmedia_vid_stream_get_stat_jbuf(
 
1813
                                            const pjmedia_vid_stream *stream,
 
1814
                                            pjmedia_jb_state *state)
 
1815
{
 
1816
    PJ_ASSERT_RETURN(stream && state, PJ_EINVAL);
 
1817
    return pjmedia_jbuf_get_state(stream->jb, state);
 
1818
}
 
1819
 
 
1820
 
 
1821
/*
 
1822
 * Get the stream info.
 
1823
 */
 
1824
PJ_DEF(pj_status_t) pjmedia_vid_stream_get_info(
 
1825
                                            const pjmedia_vid_stream *stream,
 
1826
                                            pjmedia_vid_stream_info *info)
 
1827
{
 
1828
    PJ_ASSERT_RETURN(stream && info, PJ_EINVAL);
 
1829
    pj_memcpy(info, &stream->info, sizeof(*info));
 
1830
    return PJ_SUCCESS;
 
1831
}
 
1832
 
 
1833
 
 
1834
/*
 
1835
 * Start stream.
 
1836
 */
 
1837
PJ_DEF(pj_status_t) pjmedia_vid_stream_start(pjmedia_vid_stream *stream)
 
1838
{
 
1839
 
 
1840
    PJ_ASSERT_RETURN(stream && stream->enc && stream->dec, PJ_EINVALIDOP);
 
1841
 
 
1842
    if (stream->enc && (stream->dir & PJMEDIA_DIR_ENCODING)) {
 
1843
        stream->enc->paused = 0;
 
1844
        //pjmedia_snd_stream_start(stream->enc->snd_stream);
 
1845
        PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream started"));
 
1846
    } else {
 
1847
        PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream paused"));
 
1848
    }
 
1849
 
 
1850
    if (stream->dec && (stream->dir & PJMEDIA_DIR_DECODING)) {
 
1851
        stream->dec->paused = 0;
 
1852
        //pjmedia_snd_stream_start(stream->dec->snd_stream);
 
1853
        PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream started"));
 
1854
    } else {
 
1855
        PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream paused"));
 
1856
    }
 
1857
 
 
1858
    return PJ_SUCCESS;
 
1859
}
 
1860
 
 
1861
 
 
1862
/*
 
1863
 * Check status.
 
1864
 */
 
1865
PJ_DEF(pj_bool_t) pjmedia_vid_stream_is_running(pjmedia_vid_stream *stream,
 
1866
                                                pjmedia_dir dir)
 
1867
{
 
1868
    pj_bool_t is_running = PJ_TRUE;
 
1869
 
 
1870
    PJ_ASSERT_RETURN(stream, PJ_FALSE);
 
1871
 
 
1872
    if (dir & PJMEDIA_DIR_ENCODING) {
 
1873
        is_running &= (stream->enc && !stream->enc->paused);
 
1874
    }
 
1875
 
 
1876
    if (dir & PJMEDIA_DIR_DECODING) {
 
1877
        is_running &= (stream->dec && !stream->dec->paused);
 
1878
    }
 
1879
 
 
1880
    return is_running;
 
1881
}
 
1882
 
 
1883
/*
 
1884
 * Pause stream.
 
1885
 */
 
1886
PJ_DEF(pj_status_t) pjmedia_vid_stream_pause(pjmedia_vid_stream *stream,
 
1887
                                             pjmedia_dir dir)
 
1888
{
 
1889
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
 
1890
 
 
1891
    if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) {
 
1892
        stream->enc->paused = 1;
 
1893
        PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream paused"));
 
1894
    }
 
1895
 
 
1896
    if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) {
 
1897
        stream->dec->paused = 1;
 
1898
 
 
1899
        /* Also reset jitter buffer */
 
1900
        pj_mutex_lock( stream->jb_mutex );
 
1901
        pjmedia_jbuf_reset(stream->jb);
 
1902
        pj_mutex_unlock( stream->jb_mutex );
 
1903
 
 
1904
        PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream paused"));
 
1905
    }
 
1906
 
 
1907
    return PJ_SUCCESS;
 
1908
}
 
1909
 
 
1910
 
 
1911
/*
 
1912
 * Resume stream
 
1913
 */
 
1914
PJ_DEF(pj_status_t) pjmedia_vid_stream_resume(pjmedia_vid_stream *stream,
 
1915
                                              pjmedia_dir dir)
 
1916
{
 
1917
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
 
1918
 
 
1919
    if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) {
 
1920
        stream->enc->paused = 0;
 
1921
        PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream resumed"));
 
1922
    }
 
1923
 
 
1924
    if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) {
 
1925
        stream->dec->paused = 0;
 
1926
        PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream resumed"));
 
1927
    }
 
1928
 
 
1929
    return PJ_SUCCESS;
 
1930
}
 
1931
 
 
1932
 
 
1933
/*
 
1934
 * Force stream to send video keyframe.
 
1935
 */
 
1936
PJ_DEF(pj_status_t) pjmedia_vid_stream_send_keyframe(
 
1937
                                                pjmedia_vid_stream *stream)
 
1938
{
 
1939
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
 
1940
 
 
1941
    if (!pjmedia_vid_stream_is_running(stream, PJMEDIA_DIR_ENCODING))
 
1942
        return PJ_EINVALIDOP;
 
1943
 
 
1944
    stream->force_keyframe = PJ_TRUE;
 
1945
 
 
1946
    return PJ_SUCCESS;
 
1947
}
 
1948
 
 
1949
 
 
1950
/*
 
1951
 * Send RTCP SDES.
 
1952
 */
 
1953
PJ_DEF(pj_status_t) pjmedia_vid_stream_send_rtcp_sdes(
 
1954
                                                pjmedia_vid_stream *stream)
 
1955
{
 
1956
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
 
1957
 
 
1958
    return send_rtcp(stream, PJ_TRUE, PJ_FALSE);
 
1959
}
 
1960
 
 
1961
 
 
1962
/*
 
1963
 * Send RTCP BYE.
 
1964
 */
 
1965
PJ_DEF(pj_status_t) pjmedia_vid_stream_send_rtcp_bye(
 
1966
                                                pjmedia_vid_stream *stream)
 
1967
{
 
1968
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
 
1969
 
 
1970
    if (stream->enc && stream->transport) {
 
1971
        return send_rtcp(stream, PJ_TRUE, PJ_TRUE);
 
1972
    }
 
1973
 
 
1974
    return PJ_SUCCESS;
 
1975
}
 
1976
 
 
1977
 
 
1978
/*
 
1979
 * Initialize the video stream rate control with default settings.
 
1980
 */
 
1981
PJ_DEF(void)
 
1982
pjmedia_vid_stream_rc_config_default(pjmedia_vid_stream_rc_config *cfg)
 
1983
{
 
1984
    pj_bzero(cfg, sizeof(*cfg));
 
1985
    cfg->method = PJMEDIA_VID_STREAM_RC_SIMPLE_BLOCKING;
 
1986
}
 
1987
 
 
1988
 
 
1989
#endif /* PJMEDIA_HAS_VIDEO */