~ubuntu-branches/ubuntu/trusty/mpeg4ip/trusty

« back to all changes in this revision

Viewing changes to player/src/rtp_bytestream.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mario Limonciello
  • Date: 2008-01-12 15:59:56 UTC
  • Revision ID: james.westby@ubuntu.com-20080112155956-1vznw5njidvrh649
Tags: upstream-1.6dfsg
ImportĀ upstreamĀ versionĀ 1.6dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * The contents of this file are subject to the Mozilla Public
 
3
 * License Version 1.1 (the "License"); you may not use this file
 
4
 * except in compliance with the License. You may obtain a copy of
 
5
 * the License at http://www.mozilla.org/MPL/
 
6
 * 
 
7
 * Software distributed under the License is distributed on an "AS
 
8
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
9
 * implied. See the License for the specific language governing
 
10
 * rights and limitations under the License.
 
11
 * 
 
12
 * The Original Code is MPEG4IP.
 
13
 * 
 
14
 * The Initial Developer of the Original Code is Cisco Systems Inc.
 
15
 * Portions created by Cisco Systems Inc. are
 
16
 * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
 
17
 * 
 
18
 * Contributor(s): 
 
19
 *              Bill May        wmay@cisco.com
 
20
 */
 
21
 
 
22
#include "mpeg4ip.h"
 
23
#include <rtp/rtp.h>
 
24
#include <rtp/memory.h>
 
25
#include <sdp/sdp.h> // for NTP_TO_UNIX_TIME
 
26
#include "rtp_bytestream.h"
 
27
#include "our_config_file.h"
 
28
 
 
29
//#define DEBUG_RTP_PAKS 1
 
30
//#define DEBUG_RTP_FRAMES 1
 
31
//#define DEBUG_RTP_BCAST 1
 
32
//#define DEBUG_RTP_WCLOCK 1
 
33
//#define DEBUG_RTP_TS 1
 
34
//#define DEBUG_SEQUENCE_DROPS 1
 
35
#ifdef _WIN32
 
36
DEFINE_MESSAGE_MACRO(rtp_message, "rtpbyst")
 
37
#else
 
38
#define rtp_message(loglevel, fmt...) message(loglevel, "rtpbyst", fmt)
 
39
#endif
 
40
/*
 
41
 * add_rtp_packet_to_queue() - adds rtp packet to doubly linked lists - 
 
42
 * this is used both by the bytestream, and by the player_media when trying
 
43
 * to determine which rtp payload type is being used.
 
44
 */
 
45
int add_rtp_packet_to_queue (rtp_packet *pak, 
 
46
                             rtp_packet **head,
 
47
                             rtp_packet **tail,
 
48
                             const char *name)
 
49
{
 
50
  rtp_packet *q;
 
51
  bool inserted = true;
 
52
  int16_t head_diff = 0, tail_diff = 0;
 
53
#ifdef DEBUG_RTP_PAKS
 
54
  rtp_message(LOG_DEBUG, "%s - m %u pt %u seq %u ts %x len %d", 
 
55
              name,
 
56
              pak->rtp_pak_m, pak->rtp_pak_pt, pak->rtp_pak_seq, 
 
57
              pak->rtp_pak_ts, pak->rtp_data_len);
 
58
#endif
 
59
 
 
60
  if (*head == NULL) {
 
61
    // no packets on queue
 
62
    *head = *tail = pak;
 
63
    pak->rtp_next = pak;
 
64
    pak->rtp_prev = pak;
 
65
  } else {
 
66
    // take the differences between the head and tail sequence numbers
 
67
    tail_diff = pak->rtp_pak_seq - (*tail)->rtp_pak_seq;
 
68
    head_diff = pak->rtp_pak_seq - (*head)->rtp_pak_seq;
 
69
 
 
70
    if (head_diff == 0 || tail_diff == 0) {
 
71
      // duplicate of head - ignore it
 
72
      inserted = false;
 
73
      rtp_message(LOG_ERR, "%s - Duplicate of pak sequence #%u", 
 
74
                  name, pak->rtp_pak_seq);
 
75
    } else if (head_diff > 0 && tail_diff < 0) {
 
76
      // insert in middle
 
77
      q = (*head)->rtp_next;
 
78
 
 
79
      for (q = (*head)->rtp_next; 
 
80
           q->rtp_pak_seq - pak->rtp_pak_seq <= 0;
 
81
           q = q->rtp_next);
 
82
 
 
83
      if (q->rtp_pak_seq == pak->rtp_pak_seq) {
 
84
        // duplicate
 
85
        rtp_message(LOG_ERR, "%s - duplicate pak received %u", 
 
86
                    name, pak->rtp_pak_seq);
 
87
        inserted = false;
 
88
      } else {
 
89
        rtp_message(LOG_DEBUG, "%s - insert %u before %u",
 
90
                    name, pak->rtp_pak_seq, q->rtp_pak_seq);
 
91
        // insert in the middle
 
92
        q->rtp_prev->rtp_next = pak;
 
93
        pak->rtp_prev = q->rtp_prev;
 
94
        q->rtp_prev = pak;
 
95
        pak->rtp_next = q;
 
96
      }
 
97
    } else {
 
98
      // not in the middle.  Insert between the tail and head
 
99
      (*head)->rtp_prev = pak;
 
100
      (*tail)->rtp_next = pak;
 
101
      pak->rtp_next = *head;
 
102
      pak->rtp_prev = *tail;
 
103
      if (abs(head_diff) > abs(tail_diff)) {
 
104
        *tail = pak;
 
105
      } else if (head_diff < 0 && head_diff > -10) {
 
106
        // head is closer, so, insert at begin
 
107
        rtp_message(LOG_DEBUG, "%s inserting %u at head %u tail %u",
 
108
                    name,
 
109
                    pak->rtp_pak_seq,
 
110
                    (*head)->rtp_pak_seq,
 
111
                    (*tail)->rtp_pak_seq);
 
112
        *head = pak;
 
113
      } else {
 
114
        // insert at tail
 
115
#if 0
 
116
        if (head_diff > 1000 || head_diff < -1000 ||
 
117
            tail_diff > 1000 || tail_diff < -1000) {
 
118
          rtp_message(LOG_DEBUG, "%s inserting %u at tail - head %u tail %u",
 
119
                      name, 
 
120
                      pak->rtp_pak_seq,
 
121
                      (*head)->rtp_pak_seq,
 
122
                      (*tail)->rtp_pak_seq);
 
123
        }
 
124
#endif
 
125
        *tail = pak;
 
126
      }
 
127
    }
 
128
  }
 
129
 
 
130
  if (inserted == false) {
 
131
    rtp_message(LOG_ERR, "%s Couldn't insert pak", name);
 
132
    rtp_message(LOG_DEBUG, "pak seq %u", pak->rtp_pak_seq);
 
133
    if (*head != NULL) {
 
134
      rtp_message(LOG_DEBUG, "head seq %u, tail seq %u", 
 
135
                  (*head)->rtp_pak_seq,
 
136
                  (*tail)->rtp_pak_seq);
 
137
    }
 
138
    xfree(pak);
 
139
    return (0);
 
140
  } 
 
141
  
 
142
  q = *head;
 
143
  if (q->rtp_next == *head) return 1;
 
144
#ifdef DEBUG_SEQUENCE_DROPS
 
145
  bool dump_list = false;
 
146
  int16_t diff;
 
147
  do {
 
148
    diff = q->rtp_next->rtp_pak_seq - q->rtp_pak_seq;
 
149
    if (diff < 0 || diff > 2) {
 
150
      dump_list = true;
 
151
    } else 
 
152
      q = q->rtp_next;
 
153
  } while (dump_list == false && q != *tail);
 
154
  if (dump_list) {
 
155
    rtp_message(LOG_DEBUG, "%s possible queue error - inserted %u %d %d", name,
 
156
                pak->rtp_pak_seq, head_diff, tail_diff);
 
157
    rtp_message(LOG_DEBUG, "%s seq %u %u diff %d", name, 
 
158
                q->rtp_pak_seq, q->rtp_next->rtp_pak_seq, diff);
 
159
#if 0
 
160
    q = *head;
 
161
    do {
 
162
      head_diff = q->rtp_next->rtp_pak_seq - q->rtp_pak_seq;
 
163
      rtp_message(LOG_DEBUG, "%u diff next %d", q->rtp_pak_seq, head_diff);
 
164
      q = q->rtp_next;
 
165
    } while (q != *head);
 
166
#endif
 
167
    rtp_message(LOG_DEBUG, "%s - head %u tail %u", 
 
168
                name, (*head)->rtp_pak_seq, (*tail)->rtp_pak_seq);
 
169
  }
 
170
#endif
 
171
  return (1);
 
172
}
 
173
 
 
174
CRtpByteStreamBase::CRtpByteStreamBase(const char *name,
 
175
                                       format_list_t *fmt,
 
176
                                       unsigned int rtp_pt,
 
177
                                       int ondemand,
 
178
                                       uint64_t tps,
 
179
                                       rtp_packet **head, 
 
180
                                       rtp_packet **tail,
 
181
                                       int rtp_seq_set,
 
182
                                       uint16_t rtp_base_seq,
 
183
                                       int rtp_ts_set,
 
184
                                       uint32_t rtp_base_ts,
 
185
                                       int rtcp_received,
 
186
                                       uint32_t ntp_frac,
 
187
                                       uint32_t ntp_sec,
 
188
                                       uint32_t rtp_ts) :
 
189
  COurInByteStream(name)
 
190
{
 
191
  m_fmt = fmt;
 
192
  m_head = *head;
 
193
  *head = NULL;
 
194
  m_tail = *tail;
 
195
  *tail = NULL;
 
196
 
 
197
  if (rtp_ts_set) {
 
198
    set_rtp_base_ts(rtp_base_ts);
 
199
  } else {
 
200
    m_base_ts_set = false;
 
201
  }
 
202
 
 
203
  if (rtp_seq_set) {
 
204
    set_rtp_base_seq(rtp_base_seq);
 
205
  } else {
 
206
    m_rtp_base_seq_set = false;
 
207
  }
 
208
 
 
209
  m_have_first_pak_ts = false;
 
210
  m_rtp_pt = rtp_pt;
 
211
  uint64_t temp;
 
212
  temp = config.get_config_value(CONFIG_RTP_BUFFER_TIME_MSEC);
 
213
  if (temp > 0) {
 
214
    m_rtp_buffer_time = temp;
 
215
  } else {
 
216
    m_rtp_buffer_time = TO_U64(2000);
 
217
  }
 
218
 
 
219
  m_timescale = tps;
 
220
 
 
221
  reset();
 
222
 
 
223
  m_last_rtp_ts = 0;
 
224
  m_total =0;
 
225
  m_skip_on_advance_bytes = 0;
 
226
  m_stream_ondemand = ondemand;
 
227
  m_rtcp_received = false;
 
228
  m_rtp_packet_mutex = SDL_CreateMutex();
 
229
  m_buffering = 0;
 
230
  m_eof = 0;
 
231
  m_psptr = NULL;
 
232
  m_have_sync_info = false;
 
233
  if (rtcp_received) {
 
234
    calculate_wallclock_offset_from_rtcp(ntp_frac, ntp_sec, rtp_ts);
 
235
  }
 
236
}
 
237
 
 
238
CRtpByteStreamBase::~CRtpByteStreamBase (void)
 
239
{
 
240
  flush_rtp_packets();
 
241
  if (m_rtp_packet_mutex) {
 
242
    SDL_DestroyMutex(m_rtp_packet_mutex);
 
243
    m_rtp_packet_mutex = NULL;
 
244
  }
 
245
}
 
246
 
 
247
// set_sync - this is for audio only - it will send messages to any
 
248
// video rtp bytestream to perform the syncronizatio
 
249
void CRtpByteStreamBase::set_sync (CPlayerSession *psptr) 
 
250
 
251
  m_psptr = psptr; 
 
252
}
 
253
 
 
254
void CRtpByteStreamBase::init (void)
 
255
{
 
256
  m_wrap_offset = 0;
 
257
  m_offset_in_pak = m_skip_on_advance_bytes;
 
258
  m_eof = 0;
 
259
}
 
260
void CRtpByteStreamBase::set_wallclock_offset (uint64_t wclock, 
 
261
                                               uint32_t rtp_ts) 
 
262
{
 
263
  int32_t rtp_ts_diff;
 
264
  int64_t wclock_diff;
 
265
  uint64_t wclock_calc;
 
266
  bool set = true;
 
267
  bool had_recvd_rtcp;
 
268
  if (m_rtcp_received == 1 /*&&
 
269
                             m_stream_ondemand == 0*/) {
 
270
    rtp_ts_diff = rtp_ts;
 
271
    rtp_ts_diff -= m_rtcp_rtp_ts;
 
272
    wclock_diff = (int64_t)rtp_ts_diff;
 
273
    wclock_diff *= TO_D64(1000);
 
274
    wclock_diff /= (int64_t)m_timescale;
 
275
    wclock_calc = m_rtcp_ts;
 
276
    wclock_calc += wclock_diff;
 
277
    set = false;
 
278
    if (wclock_calc != wclock) {
 
279
#ifdef DEBUG_RTP_WCLOCK
 
280
      rtp_message(LOG_DEBUG, 
 
281
                  "%s - set wallclock - wclock should be "U64" is "U64, 
 
282
                m_name, wclock_calc, wclock);
 
283
#endif
 
284
      // don't change wclock offset if it's > 100 msec - otherwise, 
 
285
      // it's annoying noise
 
286
      int64_t diff = wclock_calc - wclock;
 
287
      if (abs(diff) > 2 && abs(diff) < 100) {
 
288
        set = false;
 
289
        //      rtp_message(LOG_DEBUG, "not changing");
 
290
        // we'll allow a msec drift here or there to allow for rounding - 
 
291
        // we want this to change every so often
 
292
      }
 
293
    }
 
294
    
 
295
  }
 
296
  had_recvd_rtcp = m_rtcp_received;
 
297
  m_rtcp_received = true;
 
298
  SDL_LockMutex(m_rtp_packet_mutex);
 
299
  if (set) {
 
300
    m_rtcp_ts = wclock;
 
301
    m_rtcp_rtp_ts = rtp_ts;
 
302
  }
 
303
  if (m_have_first_pak_ts) {
 
304
    // we only want positives here
 
305
    int32_t diff;
 
306
    diff = rtp_ts - m_first_pak_rtp_ts;
 
307
    int32_t compare = 3600 * m_timescale;
 
308
#ifdef DEBUG_RTP_WCLOCK
 
309
    rtp_message(LOG_DEBUG, "%s - 1st rtp ts %u rtp %u %u", 
 
310
                m_name, m_first_pak_rtp_ts, rtp_ts, diff);
 
311
    rtp_message(LOG_DEBUG, "%s - 1st ts "U64, m_name, m_first_pak_ts);
 
312
#endif
 
313
    if (diff > compare) {
 
314
      // adjust once an hour, to keep errors low
 
315
      // we'll adjust the timestamp and rtp timestamp
 
316
      int64_t ts_diff;
 
317
      ts_diff = (int64_t)diff;
 
318
      ts_diff *= TO_U64(1000);
 
319
      ts_diff /= (int64_t)m_timescale;
 
320
      m_first_pak_ts += ts_diff;
 
321
      m_first_pak_rtp_ts += diff;
 
322
#ifdef DEBUG_RTP_WCLOCK
 
323
      rtp_message(LOG_DEBUG, "CHANGE %s - first pak ts is now "U64" rtp %u", 
 
324
                  m_name, m_first_pak_ts, m_first_pak_rtp_ts);
 
325
#endif
 
326
    }
 
327
    // We've received an RTCP - see if we need to syncronize
 
328
    // the video streams.
 
329
    if (m_psptr != NULL) {
 
330
      rtcp_sync_t sync;
 
331
      sync.first_pak_ts = m_first_pak_ts;
 
332
      sync.first_pak_rtp_ts = m_first_pak_rtp_ts;
 
333
      sync.rtcp_ts = m_rtcp_ts;
 
334
      sync.rtcp_rtp_ts = m_rtcp_rtp_ts;
 
335
      sync.timescale = m_timescale;
 
336
      m_psptr->synchronize_rtp_bytestreams(&sync);
 
337
    } else {
 
338
      // if this is our first rtcp, try to synchronize
 
339
      if (!had_recvd_rtcp) synchronize(NULL);
 
340
    }
 
341
  }
 
342
 
 
343
  SDL_UnlockMutex(m_rtp_packet_mutex);
 
344
}
 
345
 
 
346
/*
 
347
 * calculate_wallclock_offset_from_rtcp
 
348
 * Given certain information from an rtcp message, Calculate what the
 
349
 * wallclock time for rtp sequence number 0 would be.
 
350
 */
 
351
void
 
352
CRtpByteStreamBase::calculate_wallclock_offset_from_rtcp (uint32_t ntp_frac,
 
353
                                                          uint32_t ntp_sec,
 
354
                                                          uint32_t rtp_ts)
 
355
{
 
356
  uint64_t wclock;
 
357
  wclock = ntp_frac;
 
358
  wclock *= TO_U64(1000);
 
359
  wclock /= (TO_U64(1) << 32);
 
360
  uint64_t offset;
 
361
  offset = ntp_sec;
 
362
  offset -= NTP_TO_UNIX_TIME;
 
363
  offset *= TO_U64(1000);
 
364
  wclock += offset;
 
365
#ifdef DEBUG_RTP_WCLOCK
 
366
  rtp_message(LOG_DEBUG, "%s RTCP data - sec %u frac %u value "U64" ts %u", 
 
367
              m_name, ntp_sec, ntp_frac, wclock, rtp_ts);
 
368
#endif
 
369
  set_wallclock_offset(wclock, rtp_ts);
 
370
}
 
371
 
 
372
/*
 
373
 * check_buffering is called to check and see if we should be buffering
 
374
 */
 
375
int CRtpByteStreamBase::check_buffering (void)
 
376
{
 
377
  if (m_buffering == 0) {
 
378
    uint32_t head_ts, tail_ts;
 
379
    if (m_head != NULL) {
 
380
      /*
 
381
       * Payload type the same.  Make sure we have at least 2 seconds of
 
382
       * good data
 
383
       */
 
384
      if (check_rtp_frame_complete_for_payload_type()) {
 
385
        head_ts = m_head->rtp_pak_ts;
 
386
        tail_ts = m_tail->rtp_pak_ts;
 
387
        if (head_ts > tail_ts &&
 
388
            ((head_ts & (1 << 31)) == (tail_ts & (1 << 31)))) {
 
389
          return 0;
 
390
        }
 
391
        uint64_t calc;
 
392
        calc = tail_ts;
 
393
        calc -= head_ts;
 
394
        calc *= TO_U64(1000);
 
395
        calc /= m_timescale;
 
396
        if (calc >= m_rtp_buffer_time) {
 
397
          if (m_base_ts_set == false) {
 
398
            rtp_message(LOG_NOTICE, 
 
399
                        "%s - Setting rtp seq and time from 1st pak",
 
400
                        m_name);
 
401
            set_rtp_base_ts(m_head->rtp_pak_ts);
 
402
            m_rtpinfo_set_from_pak = 1;
 
403
          } else {
 
404
            m_rtpinfo_set_from_pak = 0;
 
405
          }
 
406
          m_buffering = 1;
 
407
#if 1
 
408
          rtp_message(LOG_INFO, 
 
409
                      "%s buffering complete - head seq %d %u tail seq %d %u "D64, 
 
410
                      m_name, m_head->rtp_pak_seq, head_ts, 
 
411
                      m_tail->rtp_pak_seq,
 
412
                      tail_ts, calc);
 
413
#endif
 
414
          m_next_seq = m_head->rtp_pak_seq - 1;
 
415
          
 
416
        }
 
417
      }
 
418
    }
 
419
  }
 
420
  return m_buffering;
 
421
}
 
422
  
 
423
/*
 
424
 * recv_callback - callback for when bytestream is active - basically, 
 
425
 * put things on the queue
 
426
 */
 
427
int CRtpByteStreamBase::recv_callback (struct rtp *session, rtp_event *e)
 
428
{
 
429
  switch (e->type) {
 
430
  case RX_RTP:
 
431
    rtp_packet *rpak;
 
432
    rpak = (rtp_packet *)e->data;
 
433
    if (rpak->rtp_data_len == 0) {
 
434
      xfree(rpak);
 
435
    } else {
 
436
      // need to add lock/unlock of mutex here
 
437
      if (m_have_recv_last_ts) {
 
438
        int32_t diff = rpak->rtp_pak_ts - m_recv_last_ts;
 
439
        int32_t ts, nts;
 
440
        ts = m_timescale * 2;
 
441
        nts = 0 - ts;
 
442
        if (diff > ts || diff < nts) {
 
443
          rtp_message(LOG_INFO, "%s - rtp timestamp diff %d last %u now %u", 
 
444
                      m_name, diff, m_recv_last_ts, rpak->rtp_pak_ts);
 
445
          flush_rtp_packets();
 
446
          reset();
 
447
        }
 
448
                      
 
449
      }
 
450
      m_have_recv_last_ts = true;
 
451
      m_recv_last_ts = rpak->rtp_pak_ts;
 
452
      if (m_buffering == 0) {
 
453
        rpak->pd.rtp_pd_timestamp = get_time_of_day();
 
454
        rpak->pd.rtp_pd_have_timestamp = 1;
 
455
      }
 
456
      if (SDL_mutexP(m_rtp_packet_mutex) == -1) {
 
457
        rtp_message(LOG_CRIT, "SDL Lock mutex failure in rtp bytestream recv");
 
458
        break;
 
459
      }
 
460
      add_rtp_packet_to_queue(rpak, &m_head, &m_tail, m_name);
 
461
      if (SDL_mutexV(m_rtp_packet_mutex) == -1) {
 
462
        rtp_message(LOG_CRIT, "SDL Lock mutex failure in rtp bytestream recv");
 
463
        break;
 
464
      }
 
465
      m_recvd_pak = true;
 
466
      check_buffering();
 
467
    }
 
468
    break;
 
469
  case RX_SR:
 
470
    rtcp_sr *srpak;
 
471
    srpak = (rtcp_sr *)e->data;
 
472
    if (rtp_my_ssrc(session) != e->ssrc) {
 
473
      //rtp_message(LOG_DEBUG, "%s received rtcp", m_name);
 
474
      calculate_wallclock_offset_from_rtcp(srpak->ntp_frac, 
 
475
                                           srpak->ntp_sec, 
 
476
                                           srpak->rtp_ts);
 
477
    }
 
478
    break;
 
479
  case RX_APP:
 
480
    free(e->data);
 
481
    break;
 
482
  default:
 
483
#if 0
 
484
    rtp_message(LOG_DEBUG, "Thread %u - Callback from rtp with %d %p", 
 
485
                SDL_ThreadID(),e->type, e->rtp_data);
 
486
#endif
 
487
    break;
 
488
  }
 
489
  return m_buffering;
 
490
}
 
491
 
 
492
/*
 
493
 * synchronize is used to adjust a video broadcasts time based
 
494
 * on an audio broadcasts time.
 
495
 * We now start the audio and video just based on the Unix time of the
 
496
 * first packet.  Then we use this to adjust when both sides have rtcp
 
497
 * packets.
 
498
 * It will also work if we never get in RTCP - this routine won't be
 
499
 * called - but our sync will be off.
 
500
 */
 
501
void CRtpByteStreamBase::synchronize (rtcp_sync_t *sync)
 
502
{
 
503
  // need to recalculate m_first_pak_ts here
 
504
  uint64_t adjust_first_pak_ts;
 
505
  int64_t adjust_first_pak;
 
506
  int64_t audio_diff, our_diff;
 
507
 
 
508
  if (sync == NULL) {
 
509
    if (!m_have_sync_info) return;
 
510
    sync = &m_sync_info;
 
511
  } else {
 
512
    if (m_rtcp_received == false)
 
513
      m_sync_info = *sync;
 
514
  }
 
515
  m_have_sync_info = true;
 
516
  
 
517
  if (m_psptr != NULL) return;
 
518
  if (m_rtcp_received == false) return;
 
519
  if (m_have_first_pak_ts == false) return;
 
520
  
 
521
  // First calculation - use the first packet's timestamp to calculate
 
522
  // what the timestamp value would be at the RTCP's RTP timestamp value
 
523
  // adjust_first_pak is amount we need to add to the first_packet's timestamp
 
524
  // We do this for the data we got for the audio stream
 
525
  adjust_first_pak = sync->rtcp_rtp_ts;
 
526
  adjust_first_pak -= sync->first_pak_rtp_ts;
 
527
  adjust_first_pak *= 1000;
 
528
  adjust_first_pak /= (int64_t)sync->timescale;
 
529
 
 
530
  adjust_first_pak_ts = sync->first_pak_ts;
 
531
  adjust_first_pak_ts += adjust_first_pak;
 
532
 
 
533
  // Now, we compute the difference between that value and what the RTCP
 
534
  // says the timestamp should be
 
535
  audio_diff = adjust_first_pak_ts;
 
536
  audio_diff -= sync->rtcp_ts;
 
537
 
 
538
#ifdef DEBUG_RTP_WCLOCK
 
539
  rtp_message(LOG_DEBUG, "%s - audio rtcp rtp ts %u first pak %u",
 
540
              m_name, sync->rtcp_rtp_ts, sync->first_pak_rtp_ts);
 
541
  rtp_message(LOG_DEBUG, "%s - audio rtcp ts "U64" first pak "U64,
 
542
              m_name, sync->rtcp_ts, sync->first_pak_ts);
 
543
  rtp_message(LOG_DEBUG, "%s - adjusted first pak "D64" ts "U64, 
 
544
              m_name, adjust_first_pak, sync->timescale);
 
545
  rtp_message(LOG_DEBUG, "%s - diff "D64, m_name, audio_diff);
 
546
#endif
 
547
  
 
548
  // Now, we do the same calculation for the numbers for our timestamps - 
 
549
  // find the timestamp by adjusting the first packet's timestamp to the
 
550
  // timestamp based on the current RTCP RTP timestamp;
 
551
  adjust_first_pak = m_rtcp_rtp_ts;
 
552
  adjust_first_pak -= m_first_pak_rtp_ts;
 
553
  adjust_first_pak *= 1000;
 
554
  adjust_first_pak /= (int64_t)m_timescale;
 
555
 
 
556
  adjust_first_pak_ts = m_first_pak_ts;
 
557
  adjust_first_pak_ts += adjust_first_pak;
 
558
  our_diff = adjust_first_pak_ts;
 
559
  our_diff -= m_rtcp_ts;
 
560
 
 
561
#ifdef DEBUG_RTP_WCLOCK
 
562
  rtp_message(LOG_DEBUG, "%s - our rtcp rtp ts %u first pak %u",
 
563
              m_name, m_rtcp_rtp_ts, m_first_pak_rtp_ts);
 
564
  rtp_message(LOG_DEBUG, "%s - our rtcp ts "U64" first pak "U64,
 
565
              m_name, m_rtcp_ts, m_first_pak_ts);
 
566
  rtp_message(LOG_DEBUG, "%s - adjusted first pak "D64" ts "U64, 
 
567
              m_name, adjust_first_pak, m_timescale);
 
568
  rtp_message(LOG_DEBUG, "%s - diff "D64, m_name, our_diff);
 
569
  rtp_message(LOG_INFO, "%s adjusting first pak ts by "D64, 
 
570
              m_name, 
 
571
              audio_diff - our_diff);
 
572
#endif
 
573
  // Now, we very simply add the difference between the 2 to get
 
574
  // what the equivalent start time would be.  Note that these values
 
575
  // for the first packet are not fixed - they change over time to avoid
 
576
  // wrap issues.
 
577
  m_first_pak_ts += audio_diff - our_diff;
 
578
}
 
579
 
 
580
void CRtpByteStreamBase::remove_packet_rtp_queue (rtp_packet *pak, 
 
581
                                                       int free)
 
582
{
 
583
  if (pak == NULL) return;
 
584
  SDL_LockMutex(m_rtp_packet_mutex);
 
585
  if ((m_head == pak) &&
 
586
      (m_head->rtp_next == NULL || m_head->rtp_next == m_head)) {
 
587
    m_head = NULL;
 
588
    m_tail = NULL;
 
589
  } else {
 
590
    pak->rtp_next->rtp_prev = pak->rtp_prev;
 
591
    pak->rtp_prev->rtp_next = pak->rtp_next;
 
592
    if (m_head == pak) {
 
593
      m_head = pak->rtp_next;
 
594
    }
 
595
    if (m_tail == pak) {
 
596
      m_tail = pak->rtp_prev;
 
597
    }
 
598
  }
 
599
  if (pak->rtp_data_len < 0) {
 
600
    // restore the packet data length
 
601
    pak->rtp_data_len = 0 - pak->rtp_data_len;
 
602
  }
 
603
  if (free == 1) {
 
604
    xfree(pak);
 
605
  }
 
606
  SDL_UnlockMutex(m_rtp_packet_mutex);
 
607
}
 
608
 
 
609
void CRtpByteStreamBase::flush_rtp_packets (void)
 
610
{
 
611
  rtp_message(LOG_DEBUG, "%s flushed", m_name);
 
612
  while (m_head != NULL) {
 
613
    remove_packet_rtp_queue(m_head, 1);
 
614
  }
 
615
  m_buffering = 0;
 
616
  m_recvd_pak = false;
 
617
  m_recvd_pak_timeout = false;
 
618
}
 
619
 
 
620
void CRtpByteStreamBase::pause(void)
 
621
{
 
622
  reset();
 
623
}
 
624
/*
 
625
 * rtp_periodic - called from the player media rtp task.  This basically just
 
626
 * checks for the end of the range.
 
627
 */
 
628
void CRtpByteStreamBase::rtp_periodic (void)
 
629
{
 
630
  if (m_buffering != 0) {
 
631
    if (m_recvd_pak == false) {
 
632
      if (m_recvd_pak_timeout == false) {
 
633
        m_recvd_pak_timeout_time = get_time_of_day();
 
634
#if 0
 
635
        rtp_message(LOG_DEBUG, "%s Starting timeout at "U64, 
 
636
                    m_name, m_recvd_pak_timeout_time);
 
637
#endif
 
638
      } else {
 
639
        uint64_t timeout;
 
640
        if (m_eof == 0) {
 
641
          timeout = get_time_of_day() - m_recvd_pak_timeout_time;
 
642
          if (m_stream_ondemand && get_max_playtime() != 0.0) {
 
643
            uint64_t range_end = (uint64_t)(get_max_playtime() * 1000.0);
 
644
            if (m_last_realtime + timeout >= range_end) {
 
645
              rtp_message(LOG_DEBUG, 
 
646
                          "%s Timedout at range end - last "U64" range end "U64" "U64, 
 
647
                          m_name, m_last_realtime, range_end, timeout);
 
648
              m_eof = 1;
 
649
            }
 
650
          } else {
 
651
          // broadcast - perhaps if we time out for a second or 2, we
 
652
          // should re-init rtp ?  We definately need to put some timing
 
653
          // checks here.
 
654
            session_desc_t *sptr = m_fmt->media->parent;
 
655
            if (sptr->time_desc != NULL &&
 
656
                sptr->time_desc->end_time != 0) {
 
657
              time_t this_time;
 
658
              this_time = time(NULL);
 
659
              if (this_time > sptr->time_desc->end_time && 
 
660
                  timeout >= TO_U64(1000)) {
 
661
                m_eof = 1;
 
662
              }
 
663
            }
 
664
          }
 
665
        }
 
666
      }
 
667
      m_recvd_pak_timeout = true;
 
668
    } else {
 
669
      m_recvd_pak = false;
 
670
      m_recvd_pak_timeout = false;
 
671
    }
 
672
  }
 
673
}
 
674
 
 
675
bool CRtpByteStreamBase::check_rtp_frame_complete_for_payload_type (void)
 
676
{
 
677
  return (m_head && m_tail->rtp_pak_m == 1);
 
678
}
 
679
 
 
680
bool CRtpByteStreamBase::check_seq (uint16_t seq)
 
681
{
 
682
  if (seq != m_next_seq) {
 
683
    rtp_message(LOG_INFO, "%s - rtp sequence is %u should be %u", 
 
684
                m_name, seq, m_next_seq);
 
685
    return false;
 
686
  }
 
687
  return true;
 
688
}
 
689
 
 
690
void CRtpByteStreamBase::set_last_seq (uint16_t seq)
 
691
{
 
692
  m_next_seq = seq + 1;
 
693
}
 
694
 
 
695
uint64_t CRtpByteStreamBase::rtp_ts_to_msec (uint32_t rtp_ts,
 
696
                                             uint64_t uts,
 
697
                                             uint64_t &wrap_offset)
 
698
{
 
699
  uint64_t timetick;
 
700
  uint64_t adjusted_rtp_ts;
 
701
  uint64_t adjusted_wc_rtp_ts;
 
702
  bool have_wrap = false;
 
703
  uint32_t this_mask, last_mask;
 
704
 
 
705
  last_mask = m_last_rtp_ts & (1U << 31);
 
706
  this_mask = rtp_ts & (1U << 31);
 
707
  
 
708
  if (last_mask != this_mask) {
 
709
    if (this_mask == 0) {
 
710
      wrap_offset += (TO_U64(1) << 32);
 
711
      have_wrap = true;
 
712
      rtp_message(LOG_DEBUG, "%s - have wrap %x new %x", m_name, 
 
713
                  m_last_rtp_ts, rtp_ts);
 
714
    } else {
 
715
      // need to do something here
 
716
    }
 
717
  }
 
718
 
 
719
  if (m_stream_ondemand) {
 
720
    adjusted_rtp_ts = wrap_offset;
 
721
    adjusted_rtp_ts += rtp_ts;
 
722
    adjusted_wc_rtp_ts = m_base_rtp_ts;
 
723
 
 
724
    if (adjusted_wc_rtp_ts > adjusted_rtp_ts) {
 
725
      timetick = adjusted_wc_rtp_ts - adjusted_rtp_ts;
 
726
      timetick *= TO_U64(1000);
 
727
      timetick /= m_timescale;
 
728
      if (timetick > m_play_start_time) {
 
729
        timetick = 0;
 
730
      } else {
 
731
        timetick = m_play_start_time - timetick;
 
732
      }
 
733
    } else {
 
734
      timetick = adjusted_rtp_ts - adjusted_wc_rtp_ts;
 
735
      timetick *= TO_U64(1000);
 
736
      timetick /= m_timescale;
 
737
      timetick += m_play_start_time;
 
738
    }
 
739
  } else {
 
740
    // We've got a broadcast scenario here...
 
741
    if (m_have_first_pak_ts == false) {
 
742
      // We haven't processed the first packet yet - we record
 
743
      // the data here.
 
744
      m_first_pak_rtp_ts = rtp_ts;
 
745
      m_first_pak_ts = uts;
 
746
      m_have_first_pak_ts = true;
 
747
      rtp_message(LOG_DEBUG, "%s first pak ts %u "U64, 
 
748
                  m_name, m_first_pak_rtp_ts, m_first_pak_ts);
 
749
      // if we have received RTCP, set the wallclock offset, which
 
750
      // triggers the synchronization effort.
 
751
      if (m_rtcp_received) {
 
752
        // calculate other stuff
 
753
        //rtp_message(LOG_DEBUG, "%s rtp_ts_to_msec calling wallclock", m_name);
 
754
        set_wallclock_offset(m_rtcp_ts, m_rtcp_rtp_ts);
 
755
      }
 
756
    }
 
757
    SDL_LockMutex(m_rtp_packet_mutex);
 
758
    // fairly simple calculation to calculate the timestamp
 
759
    // based on this rtp timestamp, the first pak rtp timestamp and
 
760
    // the first packet timestamp.
 
761
    int32_t adder;
 
762
    int64_t ts_adder;
 
763
    if (have_wrap) {
 
764
      adder = rtp_ts - m_first_pak_rtp_ts;
 
765
      // adjust once an hour, to keep errors low
 
766
      // we'll adjust the timestamp and rtp timestamp
 
767
      ts_adder = (int64_t)adder;
 
768
      ts_adder *= TO_D64(1000);
 
769
      ts_adder /= (int64_t)m_timescale;
 
770
      m_first_pak_ts += ts_adder;
 
771
      m_first_pak_rtp_ts = rtp_ts;
 
772
#ifdef DEBUG_RTP_BCAST
 
773
      rtp_message(LOG_DEBUG, "%s adjust for wrap - first pak ts is now "U64" rtp %u", 
 
774
                  m_name, m_first_pak_ts, m_first_pak_rtp_ts);
 
775
#endif
 
776
    }
 
777
 
 
778
    // adder could be negative here, based on the RTCP we receive
 
779
    adder = rtp_ts - m_first_pak_rtp_ts;
 
780
    ts_adder = (int64_t)adder;
 
781
    ts_adder *= TO_D64(1000);
 
782
    ts_adder /= (int64_t)m_timescale;
 
783
    timetick = m_first_pak_ts;
 
784
    timetick += ts_adder;
 
785
    SDL_UnlockMutex(m_rtp_packet_mutex);
 
786
 
 
787
#ifdef DEBUG_RTP_BCAST
 
788
    rtp_message(LOG_DEBUG, "%s ts %x base %x "U64" tp "U64" adder %d "D64,
 
789
                m_name, rtp_ts, m_first_pak_rtp_ts, m_first_pak_ts, 
 
790
                timetick, adder, ts_adder);
 
791
#endif
 
792
  }
 
793
#ifdef DEBUG_RTP_TS
 
794
  rtp_message(LOG_DEBUG,"%s time "U64" %u", m_name, timetick, rtp_ts);
 
795
#endif
 
796
  // record time
 
797
  m_last_rtp_ts = rtp_ts;
 
798
  m_last_realtime = timetick;
 
799
  return (timetick);
 
800
}
 
801
 
 
802
bool CRtpByteStreamBase::find_mbit (void)
 
803
{
 
804
  rtp_packet *temp, *first;
 
805
  if (m_head == NULL) return false;
 
806
  SDL_LockMutex(m_rtp_packet_mutex);
 
807
  first = temp = m_head;
 
808
  do {
 
809
    if (temp->rtp_pak_m == 1) {
 
810
      SDL_UnlockMutex(m_rtp_packet_mutex);
 
811
      return true;
 
812
    }
 
813
    temp = temp->rtp_next;
 
814
  } while (temp != NULL && temp != first);
 
815
  SDL_UnlockMutex(m_rtp_packet_mutex);
 
816
  return false;
 
817
}
 
818
void CRtpByteStreamBase::display_status(void)
 
819
{
 
820
  SDL_LockMutex(m_rtp_packet_mutex);
 
821
  rtp_packet *pak;
 
822
  uint32_t count;
 
823
  int32_t diff;
 
824
  if (m_head == NULL) {
 
825
    rtp_message(LOG_DEBUG, "%s - no packets", m_name);
 
826
    rtp_message(LOG_DEBUG, "%s - last rtp %u last realtime "U64 " wrap "U64,
 
827
                m_name, m_last_rtp_ts, m_last_realtime, m_wrap_offset);
 
828
    SDL_UnlockMutex(m_rtp_packet_mutex);
 
829
    return;
 
830
  }
 
831
  pak = m_head;
 
832
  count = 1;
 
833
  for (pak = m_head; pak->rtp_next != m_head; pak = pak->rtp_next) count++;
 
834
  diff = m_tail->rtp_pak_ts - m_head->rtp_pak_ts;
 
835
  rtp_message(LOG_DEBUG, "%s - %u paks head seq %u ts %u tail seq %u ts %u "D64, 
 
836
              m_name, count, m_head->rtp_pak_seq, m_head->rtp_pak_ts, 
 
837
              m_tail->rtp_pak_seq, m_tail->rtp_pak_ts, diff * 1000 / m_timescale);
 
838
  rtp_message(LOG_DEBUG, "%s - last rtp %u last realtime "U64 " wrap "U64,
 
839
              m_name, m_last_rtp_ts, m_last_realtime, m_wrap_offset);
 
840
  uint32_t last_rtp_ts = m_last_rtp_ts;
 
841
  uint64_t last_realtime = m_last_realtime;
 
842
  uint64_t wrap_offset = m_wrap_offset;
 
843
  uint64_t msec = rtp_ts_to_msec(m_head->rtp_pak_ts, 
 
844
                                 m_head->pd.rtp_pd_timestamp,
 
845
                                 wrap_offset);
 
846
  m_last_rtp_ts = last_rtp_ts;
 
847
  m_last_realtime = last_realtime;
 
848
  rtp_message(LOG_DEBUG, "head ts "U64, msec);
 
849
  
 
850
#if 0
 
851
  int64_t t1, t2;
 
852
  t1 = (int64_t)m_first_pak_rtp_ts;
 
853
  t2 = (int64_t)m_first_pak_ts;
 
854
  rtp_message(LOG_DEBUG, "%s - first %u "D64" real "U64" "D64, m_name,
 
855
              m_first_pak_rtp_ts, t1, m_first_pak_ts, t2);
 
856
#endif
 
857
  SDL_UnlockMutex(m_rtp_packet_mutex);
 
858
}
 
859
 
 
860
CRtpByteStream::CRtpByteStream(const char *name,
 
861
                               format_list_t *fmt,
 
862
                               unsigned int rtp_pt,
 
863
                               int ondemand,
 
864
                               uint64_t tickpersec,
 
865
                               rtp_packet **head, 
 
866
                               rtp_packet **tail,
 
867
                               int rtp_seq_set,
 
868
                               uint16_t rtp_base_seq,
 
869
                               int rtp_ts_set,
 
870
                               uint32_t rtp_base_ts,
 
871
                               int rtcp_received,
 
872
                               uint32_t ntp_frac,
 
873
                               uint32_t ntp_sec,
 
874
                               uint32_t rtp_ts) :
 
875
  CRtpByteStreamBase(name, fmt, rtp_pt, ondemand, tickpersec, head, tail,
 
876
                     rtp_seq_set, rtp_base_seq, rtp_ts_set, rtp_base_ts, 
 
877
                     rtcp_received, ntp_frac, ntp_sec, rtp_ts)
 
878
{
 
879
  m_buffer = (uint8_t *)malloc(4096);
 
880
  m_buffer_len_max = 4096;
 
881
  m_bytes_used = m_buffer_len = 0;
 
882
}
 
883
 
 
884
CRtpByteStream::~CRtpByteStream (void)
 
885
{
 
886
  free(m_buffer);
 
887
  m_buffer = NULL;
 
888
}
 
889
 
 
890
void CRtpByteStream::reset (void)
 
891
{
 
892
  m_buffer_len = m_bytes_used = 0;
 
893
  CRtpByteStreamBase::reset();
 
894
}
 
895
 
 
896
bool CRtpByteStream::start_next_frame (uint8_t **buffer, 
 
897
                                       uint32_t *buflen,
 
898
                                       frame_timestamp_t *pts,
 
899
                                       void **ud)
 
900
{
 
901
  uint16_t seq = 0;
 
902
  uint32_t rtp_ts = 0;
 
903
  uint64_t timetick;
 
904
  uint64_t ts = 0;
 
905
  int first = 0;
 
906
  int finished = 0;
 
907
  rtp_packet *rpak;
 
908
  int32_t diff;
 
909
 
 
910
  diff = m_buffer_len - m_bytes_used;
 
911
 
 
912
  if (diff >= 2) {
 
913
    // Still bytes in the buffer...
 
914
    *buffer = m_buffer + m_bytes_used;
 
915
    *buflen = diff;
 
916
#ifdef DEBUG_RTP_FRAMES
 
917
    rtp_message(LOG_DEBUG, "%s Still left - %d bytes", m_name, *buflen);
 
918
#endif
 
919
#if 0
 
920
    rtp_message(LOG_DEBUG, "%s start %02x %02x %02x %02x %02x", m_name,
 
921
                (*buffer)[0],
 
922
                (*buffer)[1],
 
923
                (*buffer)[2],
 
924
                (*buffer)[3],
 
925
                (*buffer)[4]);
 
926
#endif
 
927
    pts->msec_timestamp = m_last_realtime;
 
928
    pts->audio_freq_timestamp = m_last_rtp_ts;
 
929
    pts->audio_freq = m_timescale;
 
930
    pts->timestamp_is_pts = true;
 
931
    return true;
 
932
  } else {
 
933
    check_seq(m_head->rtp_pak_seq);
 
934
 
 
935
    m_buffer_len = 0;
 
936
    while (finished == 0) {
 
937
      rpak = m_head;
 
938
      if (rpak == NULL) { 
 
939
        // incomplete frame - bail on this
 
940
        player_error_message("%s - This should never happen - rtp bytestream"
 
941
                             "is incomplete and active", m_name);
 
942
        player_error_message("Please report to mpeg4ip");
 
943
        player_error_message("first %d seq %u ts %x blen %d",
 
944
                             first, seq, rtp_ts, m_buffer_len);
 
945
        m_buffer_len = 0;
 
946
        m_bytes_used = 0;
 
947
        return 0;
 
948
      }
 
949
        
 
950
      remove_packet_rtp_queue(rpak, 0);
 
951
      
 
952
      if (first == 0) {
 
953
        seq = rpak->rtp_pak_seq + 1;
 
954
        ts = rpak->pd.rtp_pd_timestamp;
 
955
        rtp_ts = rpak->rtp_pak_ts;
 
956
        first = 1;
 
957
      } else {
 
958
        if ((seq != rpak->rtp_pak_seq) ||
 
959
            (rtp_ts != rpak->rtp_pak_ts)) {
 
960
          if (seq != rpak->rtp_pak_seq) {
 
961
            rtp_message(LOG_INFO, "%s missing rtp sequence - should be %u is %u", 
 
962
                        m_name, seq, rpak->rtp_pak_seq);
 
963
          } else {
 
964
            rtp_message(LOG_INFO, "%s timestamp error - seq %u should be %x is %x", 
 
965
                        m_name, seq, rtp_ts, rpak->rtp_pak_ts);
 
966
          }
 
967
          m_buffer_len = 0;
 
968
          rtp_ts = rpak->rtp_pak_ts;
 
969
        }
 
970
        seq = rpak->rtp_pak_seq + 1;
 
971
      }
 
972
      uint8_t *from;
 
973
      uint32_t len;
 
974
      from = (uint8_t *)rpak->rtp_data + m_skip_on_advance_bytes;
 
975
      len = rpak->rtp_data_len - m_skip_on_advance_bytes;
 
976
      if ((m_buffer_len + len) >= m_buffer_len_max) {
 
977
        // realloc
 
978
        m_buffer_len_max = m_buffer_len + len + 1024;
 
979
        m_buffer = (uint8_t *)realloc(m_buffer, m_buffer_len_max);
 
980
      }
 
981
      memcpy(m_buffer + m_buffer_len, 
 
982
             from,
 
983
             len);
 
984
      m_buffer_len += len;
 
985
      if (rpak->rtp_pak_m == 1) {
 
986
        finished = 1;
 
987
      }
 
988
      set_last_seq(rpak->rtp_pak_seq);
 
989
      xfree(rpak);
 
990
    }
 
991
    m_bytes_used = 0;
 
992
    *buffer = m_buffer + m_bytes_used;
 
993
    *buflen = m_buffer_len - m_bytes_used;
 
994
#if 0
 
995
  rtp_message(LOG_DEBUG, "%s start %02x %02x %02x %02x %02x", m_name,
 
996
                        (*buffer)[0],
 
997
                        (*buffer)[1],
 
998
                        (*buffer)[2],
 
999
                        (*buffer)[3],
 
1000
                        (*buffer)[4]);
 
1001
#endif
 
1002
#ifdef DEBUG_RTP_FRAMES
 
1003
    rtp_message(LOG_DEBUG, "%s buffer len %d", m_name, m_buffer_len);
 
1004
#endif
 
1005
  }
 
1006
  timetick = rtp_ts_to_msec(rtp_ts, ts, m_wrap_offset);
 
1007
  m_last_rtp_ts = rtp_ts;
 
1008
  
 
1009
  pts->msec_timestamp = timetick;
 
1010
  pts->audio_freq_timestamp = m_last_rtp_ts;
 
1011
  pts->audio_freq = m_timescale;
 
1012
  pts->timestamp_is_pts = true;
 
1013
  return (true);
 
1014
}
 
1015
 
 
1016
bool CRtpByteStream::skip_next_frame (frame_timestamp_t *pts, 
 
1017
                                     int *hasSyncFrame,
 
1018
                                     uint8_t **buffer, 
 
1019
                                     uint32_t *buflen,
 
1020
                                     void **ud)
 
1021
{
 
1022
  uint64_t ts;
 
1023
  *hasSyncFrame = -1;  // we don't know if we have a sync frame
 
1024
  m_buffer_len = m_bytes_used = 0;
 
1025
  if (m_head == NULL) return false;
 
1026
  ts = m_head->rtp_pak_ts;
 
1027
  do {
 
1028
    set_last_seq(m_head->rtp_pak_seq);
 
1029
    remove_packet_rtp_queue(m_head, 1);
 
1030
  } while (m_head != NULL && m_head->rtp_pak_ts == ts);
 
1031
 
 
1032
  if (m_head == NULL) return false;
 
1033
  init();
 
1034
  m_buffer_len = m_bytes_used = 0;
 
1035
  return start_next_frame(buffer, buflen, pts, ud);
 
1036
}
 
1037
 
 
1038
void CRtpByteStream::used_bytes_for_frame (uint32_t bytes)
 
1039
{
 
1040
  m_bytes_used += bytes;
 
1041
#ifdef DEBUG_RTP_FRAMES
 
1042
  rtp_message(LOG_DEBUG, "%s Used %d bytes", m_name, bytes);
 
1043
#endif
 
1044
}
 
1045
 
 
1046
bool CRtpByteStream::have_frame (void)
 
1047
{
 
1048
  return find_mbit();
 
1049
}
 
1050
 
 
1051
void CRtpByteStream::flush_rtp_packets (void)
 
1052
{
 
1053
  CRtpByteStreamBase::flush_rtp_packets();
 
1054
 
 
1055
  m_bytes_used = m_buffer_len = 0;
 
1056
}
 
1057
 
 
1058
 
 
1059
  
 
1060
CAudioRtpByteStream::CAudioRtpByteStream (unsigned int rtp_pt,
 
1061
                                          format_list_t *fmt,
 
1062
                                          int ondemand,
 
1063
                                          uint64_t tps,
 
1064
                                          rtp_packet **head, 
 
1065
                                          rtp_packet **tail,
 
1066
                                          int rtp_seq_set,
 
1067
                                          uint16_t rtp_base_seq,
 
1068
                                          int rtp_ts_set,
 
1069
                                          uint32_t rtp_base_ts,
 
1070
                                          int rtcp_received,
 
1071
                                          uint32_t ntp_frac,
 
1072
                                          uint32_t ntp_sec,
 
1073
                                          uint32_t rtp_ts) :
 
1074
  CRtpByteStream("audio", 
 
1075
                 fmt,
 
1076
                 rtp_pt,
 
1077
                 ondemand,
 
1078
                 tps,
 
1079
                 head, 
 
1080
                 tail,
 
1081
                 rtp_seq_set, rtp_base_seq, 
 
1082
                 rtp_ts_set, rtp_base_ts,
 
1083
                 rtcp_received,
 
1084
                 ntp_frac,
 
1085
                 ntp_sec,
 
1086
                 rtp_ts)
 
1087
{
 
1088
  init();
 
1089
  m_working_pak = NULL;
 
1090
}
 
1091
 
 
1092
CAudioRtpByteStream::~CAudioRtpByteStream(void)
 
1093
{
 
1094
}
 
1095
 
 
1096
bool CAudioRtpByteStream::have_frame (void)
 
1097
{
 
1098
  if (m_head == NULL) {
 
1099
    if (m_working_pak != NULL && m_bytes_used < m_working_pak->rtp_data_len) {
 
1100
      return true;
 
1101
    }
 
1102
    return false;
 
1103
  }
 
1104
  return true;
 
1105
}
 
1106
 
 
1107
bool CAudioRtpByteStream::check_rtp_frame_complete_for_payload_type (void)
 
1108
{
 
1109
  return m_head != NULL;
 
1110
}
 
1111
 
 
1112
void CAudioRtpByteStream::reset (void)
 
1113
{
 
1114
  rtp_message(LOG_DEBUG, "in audiortpreset");
 
1115
  CRtpByteStream::reset();
 
1116
}
 
1117
 
 
1118
void CAudioRtpByteStream::flush_rtp_packets(void) 
 
1119
{
 
1120
  if (m_working_pak != NULL) {
 
1121
    xfree(m_working_pak);
 
1122
    m_working_pak = NULL;
 
1123
  }
 
1124
  CRtpByteStream::flush_rtp_packets();
 
1125
}
 
1126
  
 
1127
bool CAudioRtpByteStream::start_next_frame (uint8_t **buffer, 
 
1128
                                            uint32_t *buflen,
 
1129
                                            frame_timestamp_t *pts,
 
1130
                                            void **ud)
 
1131
{
 
1132
  uint32_t ts;
 
1133
  int32_t diff;
 
1134
 
 
1135
  if (m_working_pak != NULL) {
 
1136
    diff = m_working_pak->rtp_data_len - m_bytes_used;
 
1137
  } else diff = 0;
 
1138
 
 
1139
  if (diff > 0) {
 
1140
    // Still bytes in the buffer...
 
1141
    *buffer = (uint8_t *)m_working_pak->rtp_data + m_bytes_used;
 
1142
    *buflen = diff;
 
1143
    pts->msec_timestamp = m_last_realtime;
 
1144
    pts->audio_freq_timestamp = m_last_rtp_ts;
 
1145
    pts->audio_freq = m_timescale;
 
1146
    pts->timestamp_is_pts = false;
 
1147
#ifdef DEBUG_RTP_FRAMES
 
1148
    rtp_message(LOG_DEBUG, "%s Still left - %d bytes", m_name, *buflen);
 
1149
#endif
 
1150
    return true;
 
1151
  } else {
 
1152
    if (m_working_pak) xfree(m_working_pak);
 
1153
    m_buffer_len = 0;
 
1154
    m_bytes_used = m_skip_on_advance_bytes;
 
1155
    m_working_pak = m_head;
 
1156
    check_seq(m_working_pak->rtp_pak_seq);
 
1157
    set_last_seq(m_working_pak->rtp_pak_seq);
 
1158
    remove_packet_rtp_queue(m_working_pak, 0);
 
1159
 
 
1160
    *buffer = (uint8_t *)m_working_pak->rtp_data + m_bytes_used;
 
1161
    *buflen = m_working_pak->rtp_data_len;
 
1162
    ts = m_working_pak->rtp_pak_ts;
 
1163
#ifdef DEBUG_RTP_FRAMES
 
1164
    rtp_message(LOG_DEBUG, "%s buffer seq %d ts %x len %d", m_name, 
 
1165
                m_working_pak->rtp_pak_seq, 
 
1166
                m_working_pak->rtp_pak_ts, *buflen);
 
1167
#endif
 
1168
  }
 
1169
 
 
1170
  // We're going to have to handle wrap better...
 
1171
  uint64_t retts = rtp_ts_to_msec(ts, 
 
1172
                                  m_working_pak->pd.rtp_pd_timestamp,
 
1173
                                  m_wrap_offset);
 
1174
  
 
1175
  m_last_rtp_ts = ts;
 
1176
  pts->msec_timestamp = retts;
 
1177
  pts->audio_freq_timestamp = m_last_rtp_ts;
 
1178
  pts->audio_freq = m_timescale;
 
1179
  pts->timestamp_is_pts = false;
 
1180
  return true;
 
1181
}