mpeg3_rtp_bytestream.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:8k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  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. #include "systems.h"
  22. #include <rtp/rtp.h>
  23. #include <rtp/memory.h>
  24. #include <sdp/sdp.h> // for NTP_TO_UNIX_TIME
  25. #include "mpeg3_rtp_bytestream.h"
  26. #include "our_config_file.h"
  27. //#define DEBUG_RTP_PAKS 1
  28. #ifdef _WIN32
  29. DEFINE_MESSAGE_MACRO(rtp_message, "rtpbyst")
  30. #else
  31. #define rtp_message(loglevel, fmt...) message(loglevel, "rtpbyst", fmt)
  32. #endif
  33. static rtp_packet *end_of_pak (rtp_packet *start)
  34. {
  35.   while (start->rtp_next->rtp_pak_ts == start->rtp_pak_ts) 
  36.     start = start->rtp_next;
  37.   return start;
  38. }
  39. CMpeg3RtpByteStream::CMpeg3RtpByteStream(unsigned int rtp_pt,
  40.  format_list_t *fmt,
  41.  int ondemand,
  42.  uint64_t tickpersec,
  43.  rtp_packet **head, 
  44.  rtp_packet **tail,
  45.  int rtp_seq_set,
  46.  uint16_t rtp_base_seq,
  47.  int rtp_ts_set,
  48.  uint32_t rtp_base_ts,
  49.  int rtcp_received,
  50.  uint32_t ntp_frac,
  51.  uint32_t ntp_sec,
  52.  uint32_t rtp_ts) :
  53.   CRtpByteStream("mpeg3", fmt, rtp_pt, ondemand, tickpersec, head, tail,
  54.  rtp_seq_set, rtp_base_seq, rtp_ts_set, rtp_base_ts, 
  55.  rtcp_received, ntp_frac, ntp_sec, rtp_ts)
  56. {
  57. }
  58. uint64_t CMpeg3RtpByteStream::start_next_frame (uint8_t **buffer, 
  59. uint32_t *buflen,
  60. void **ud)
  61. {
  62.   uint16_t seq = 0;
  63.   uint32_t ts = 0, outts;
  64.   uint64_t timetick;
  65.   int first = 0;
  66.   int finished = 0;
  67.   rtp_packet *rpak;
  68.   int32_t diff;
  69.   int correct_hdr;
  70.   int dropped_seq;
  71.   diff = m_buffer_len - m_bytes_used;
  72.   m_doing_add = 0;
  73.   if (diff > 2) {
  74.     // Still bytes in the buffer...
  75.     *buffer = m_buffer + m_bytes_used;
  76.     *buflen = diff;
  77. #ifdef DEBUG_RTP_PAKS
  78.     rtp_message(LOG_DEBUG, "%s Still left - %d bytes", m_name, *buflen);
  79. #endif
  80.     return (m_last_realtime);
  81.   }
  82.   int frame_type;
  83.   m_buffer_len = 0;
  84.   dropped_seq = 0;
  85.   while (finished == 0) {
  86.     rpak = m_head;
  87.     if (rpak == NULL) {
  88.       *buffer = NULL;
  89.       return 0;
  90.     }
  91.     remove_packet_rtp_queue(rpak, 0);
  92.     correct_hdr = 1;
  93.     if (m_next_seq != rpak->rtp_pak_seq) {
  94.       correct_hdr = 0;
  95.       rtp_message(LOG_INFO, "%s missing rtp sequence - should be %u is %u", 
  96.   m_name, m_next_seq, rpak->rtp_pak_seq);
  97.       first = 0;
  98.     } else {
  99.       if (first == 0) {
  100. ts = rpak->rtp_pak_ts;
  101. first = 1;
  102.       } else {
  103. if (ts != rpak->rtp_pak_ts) {
  104.   rtp_message(LOG_INFO, 
  105.       "%s timestamp error - seq %u should be %x is %x", 
  106.       m_name, seq, ts, rpak->rtp_pak_ts);
  107.   correct_hdr = 0;
  108. }
  109. ts = rpak->rtp_pak_ts;
  110.       }
  111.     }
  112.     if (correct_hdr == 0) {
  113.       m_buffer_len = 0;
  114.     } else {
  115.       dropped_seq = 1;
  116.     }
  117.     m_next_seq = rpak->rtp_pak_seq + 1; // handles wrap correctly
  118.     uint8_t *from;
  119.     uint32_t len;
  120.     m_skip_on_advance_bytes = 4;
  121.     if ((*rpak->rtp_data & 0x4) != 0) {
  122.       m_skip_on_advance_bytes = 8;
  123.       if ((rpak->rtp_data[4] & 0x40) != 0) {
  124.       }
  125.     }
  126.     frame_type = rpak->rtp_data[2] & 0x7;
  127.     from = (uint8_t *)rpak->rtp_data + m_skip_on_advance_bytes;
  128.     len = rpak->rtp_data_len - m_skip_on_advance_bytes;
  129.     if ((m_buffer_len + len) > m_buffer_len_max) {
  130.       // realloc
  131.       m_buffer_len_max = m_buffer_len + len + 1024;
  132.       m_buffer = (uint8_t *)realloc(m_buffer, m_buffer_len_max);
  133.     }
  134.     memcpy(m_buffer + m_buffer_len, 
  135.    from,
  136.    len);
  137.     m_buffer_len += len;
  138.   
  139.     if (rpak->rtp_pak_m == 1) {
  140.       finished = 1;
  141.     }
  142.     xfree(rpak);
  143.   }
  144.   m_bytes_used = 0;
  145.   *buffer = m_buffer + m_bytes_used;
  146.   *buflen = m_buffer_len - m_bytes_used;
  147. #ifdef DEBUG_RTP_PAKS
  148.   rtp_message(LOG_DEBUG, "%s buffer len %d", m_name, m_buffer_len);
  149. #endif
  150.   if (dropped_seq) {
  151.     outts = calc_this_ts_from_future(frame_type, ts);
  152.   } else {
  153.     if (m_have_prev_frame_type) {
  154.       if (frame_type < 3) {
  155. // B frame
  156. outts = ts + m_rtp_frame_add;
  157.       } else {
  158. outts = m_prev_ts + m_rtp_frame_add;
  159.       }
  160.     } else 
  161.       outts = calc_this_ts_from_future(frame_type, ts);
  162.   }
  163. #ifdef MPEG3_RTP_TIME
  164.   rtp_message(LOG_DEBUG, "frame type %d pak ts %u out ts %u", frame_type, 
  165.       ts, outts);
  166. #endif
  167.   m_have_prev_frame_type = 1;
  168.   m_prev_frame_type = frame_type;
  169.   m_prev_ts = outts;
  170.   if (m_rtpinfo_set_from_pak != 0) {
  171.     if (outts < m_rtp_base_ts) {
  172.       m_rtp_base_ts = outts;
  173.     }
  174.     m_rtpinfo_set_from_pak = 0;
  175.   }
  176.   m_ts = outts;
  177.   timetick = rtp_ts_to_msec(outts, m_wrap_offset);
  178.   
  179.   return (timetick);
  180. }
  181. uint32_t CMpeg3RtpByteStream::calc_this_ts_from_future (int frame_type,
  182.    uint32_t pak_ts)
  183. {
  184.   int new_frame_type;
  185.   uint32_t outts;
  186.   if (frame_type >= 3) {
  187.     // B frame - ts is always pak_ts + 1 frame time
  188.     return pak_ts + m_rtp_frame_add;
  189.   }
  190.   SDL_LockMutex(m_rtp_packet_mutex);
  191.   if (m_head->rtp_pak_seq != m_next_seq) {
  192.     outts = m_head->rtp_pak_ts - m_rtp_frame_add; // not accurate, but close enuff
  193.   } else {
  194.     new_frame_type = m_head->rtp_data[2] & 0x7;
  195.     if (new_frame_type >= 3) {
  196.       outts = m_head->rtp_pak_ts;
  197.     }  else if (frame_type == 2 ||
  198. (frame_type == 1 && new_frame_type == 1)) {
  199.     // I frame followed by I frame, P frame followed by I or P frame
  200.       outts = pak_ts;
  201.     } else {
  202.       // I frame followed by P frame
  203.       rtp_packet *next_pak = end_of_pak(m_head);
  204.       next_pak = next_pak->rtp_next;
  205.       new_frame_type = next_pak->rtp_data[2] & 0x7;
  206.       if (new_frame_type < 3) {
  207. outts = pak_ts;
  208.       } else {
  209. outts = next_pak->rtp_pak_ts - (2 * m_rtp_frame_add);
  210.       }
  211.     }
  212.   }
  213.   SDL_UnlockMutex(m_rtp_packet_mutex);
  214.   return outts;
  215. }
  216. int CMpeg3RtpByteStream::skip_next_frame (uint64_t *pts, int *hasSyncFrame,
  217.   uint8_t **buffer, 
  218.   uint32_t *buflen)
  219. {
  220.   uint64_t ts;
  221.   *hasSyncFrame = -1;  // we don't know if we have a sync frame
  222.   m_buffer_len = m_bytes_used = 0;
  223.   if (m_head == NULL) return 0;
  224.   ts = m_head->rtp_pak_ts;
  225.   do {
  226.     remove_packet_rtp_queue(m_head, 1);
  227.   } while (m_head != NULL && m_head->rtp_pak_ts == ts);
  228.   if (m_head == NULL) return 0;
  229.   init();
  230.   m_buffer_len = m_bytes_used = 0;
  231.   ts = start_next_frame(buffer, buflen, NULL);
  232.   *pts = ts;
  233.   return (1);
  234. }
  235. int CMpeg3RtpByteStream::have_no_data (void)
  236. {
  237.   rtp_packet *temp, *first;
  238.   if (m_head == NULL) return TRUE;
  239.   first = temp = m_head;
  240.   int count = 0;
  241.   SDL_LockMutex(m_rtp_packet_mutex);
  242.   do {
  243.     if (temp->rtp_pak_m == 1) {
  244.       count++;
  245.       if (count > 1) {
  246. SDL_UnlockMutex(m_rtp_packet_mutex);
  247. return FALSE;
  248.       }
  249.     }
  250.     temp = temp->rtp_next;
  251.   } while (temp != NULL && temp != first);
  252.   SDL_UnlockMutex(m_rtp_packet_mutex);
  253.   return TRUE;
  254. }
  255. void CMpeg3RtpByteStream::rtp_done_buffering (void) 
  256. {
  257.   rtp_packet *p, *q;
  258.   int had_b;
  259.   SDL_LockMutex(m_rtp_packet_mutex);
  260.   m_next_seq = m_head->rtp_pak_seq;
  261.   p = end_of_pak(m_head);
  262.   had_b = 0;
  263.   while (p != m_head) {
  264.     q = end_of_pak(p->rtp_next);
  265.     if ((p->rtp_data[2] & 0x7) == 3) {
  266.       // B frame 
  267.       had_b = 1;
  268.       if ((((q->rtp_pak_seq + 1) & 0xffff) == q->rtp_next->rtp_pak_seq) &&
  269.   ((q->rtp_next->rtp_data[2] & 0x7) == 3)) {
  270. // 2 consec b frames
  271. q = q->rtp_next;
  272. m_rtp_frame_add  = q->rtp_pak_ts - p->rtp_pak_ts;
  273. #ifdef MPEG3_RTP_TIME
  274. rtp_message(LOG_DEBUG, "2 consec b frames %d", m_rtp_frame_add);
  275. #endif
  276. SDL_UnlockMutex(m_rtp_packet_mutex);
  277. return;
  278.       }
  279.     }
  280.     p = q->rtp_next;
  281.   }
  282.   if (had_b == 0) {
  283.     // no b frames 
  284.     p = end_of_pak(m_head);
  285.     while (p != m_head) {
  286.       q = end_of_pak(p->rtp_next);
  287.       if (((q->rtp_pak_seq + 1) & 0xffff) == q->rtp_next->rtp_pak_seq) {
  288. q = q->rtp_next;
  289. m_rtp_frame_add  = q->rtp_pak_ts - p->rtp_pak_ts;
  290. SDL_UnlockMutex(m_rtp_packet_mutex);
  291. return;
  292.       }
  293.       p = q->rtp_next;
  294.     }
  295.   }
  296.   m_buffering = 0;
  297.   SDL_UnlockMutex(m_rtp_packet_mutex);
  298.   flush_rtp_packets();
  299. }