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

流媒体/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. 2000, 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  *              Bill May        wmay@cisco.com
  20.  */
  21. /*
  22.  * player_media.cpp - handle generic information about a stream
  23.  */
  24. #include "systems.h"
  25. #include "player_session.h"
  26. #include "player_media.h"
  27. #include "player_sdp.h"
  28. #include "player_util.h"
  29. #include <rtp/memory.h>
  30. #include "rtp_bytestream.h"
  31. #include "our_config_file.h"
  32. #include "media_utils.h"
  33. #include "ip_port.h"
  34. #include "codec_plugin.h"
  35. #include "audio.h"
  36. //#define DROP_PAKS 1
  37. /*
  38.  * c routines for callbacks
  39.  */
  40. static int c_recv_thread (void *data)
  41. {
  42.   CPlayerMedia *media;
  43.   media = (CPlayerMedia *)data;
  44.   return (media->recv_thread());
  45. }
  46. static void c_recv_callback (struct rtp *session, rtp_event *e)
  47. {
  48.   CPlayerMedia *m = (CPlayerMedia *)rtp_get_userdata(session);
  49.   m->recv_callback(session, e);
  50. }
  51. static int c_decode_thread (void *data)
  52. {
  53.   CPlayerMedia *media;
  54.   media = (CPlayerMedia *)data;
  55.   return (media->decode_thread());
  56. }
  57. static void c_rtp_packet_callback (void *data, 
  58.    unsigned char interleaved, 
  59.    struct rtp_packet *pak, 
  60.    int len)
  61. {
  62.   ((CPlayerMedia *)data)->rtp_receive_packet(interleaved, pak, len);
  63. }
  64. static int c_init_rtp_tcp (void *data)
  65. {
  66.   ((CPlayerMedia *)data)->rtp_init_tcp();
  67.   return 0;
  68. }
  69. static int c_rtp_start (void *data)
  70. {
  71.   ((CPlayerMedia *)data)->rtp_start();
  72.   return 0;
  73. }
  74. static int c_rtp_periodic (void *data)
  75. {
  76.   ((CPlayerMedia *)data)->rtp_periodic();
  77.   return 0;
  78. }
  79. static int c_rtcp_send_packet (void *ud, uint8_t *buffer, int buflen)
  80. {
  81.   return ((CPlayerMedia *)ud)->rtcp_send_packet(buffer, buflen);
  82. }
  83. CPlayerMedia::CPlayerMedia (CPlayerSession *p)
  84. {
  85.   m_plugin = NULL;
  86.   m_plugin_data = NULL;
  87.   m_next = NULL;
  88.   m_parent = p;
  89.   m_media_info = NULL;
  90.   m_media_fmt = NULL;
  91.   m_our_port = 0;
  92.   m_ports = NULL;
  93.   m_server_port = 0;
  94.   m_source_addr = NULL;
  95.   m_recv_thread = NULL;
  96.   m_rtptime_tickpersec = 0;
  97.   m_rtsp_base_seq_received = 0;
  98.   m_rtsp_base_ts_received = 0;
  99.   m_head = NULL;
  100.   m_rtp_queue_len = 0;
  101.   m_rtp_ssrc_set = FALSE;
  102.   
  103.   m_rtsp_session = NULL;
  104.   m_decode_thread_waiting = 0;
  105.   m_sync_time_set = FALSE;
  106.   m_decode_thread = NULL;
  107.   m_decode_thread_sem = NULL;
  108.   m_video_sync = NULL;
  109.   m_audio_sync = NULL;
  110.   m_paused = 0;
  111.   m_byte_stream = NULL;
  112.   m_rtp_byte_stream = NULL;
  113.   m_video_info = NULL;
  114.   m_audio_info = NULL;
  115.   m_user_data = NULL;
  116.   m_rtcp_received = 0;
  117.   m_streaming = 0;
  118.   m_rtp_use_rtsp = 0;
  119. }
  120. CPlayerMedia::~CPlayerMedia()
  121. {
  122.   rtsp_decode_t *rtsp_decode;
  123.   media_message(LOG_DEBUG, "closing down media %d", m_is_video);
  124.   if (m_rtsp_session) {
  125.     // If control is aggregate, m_rtsp_session will be freed by
  126.     // CPlayerSession
  127.     if (m_parent->session_control_is_aggregate() == 0) {
  128.       rtsp_send_teardown(m_rtsp_session, NULL, &rtsp_decode);
  129.       free_decode_response(rtsp_decode);
  130.     }
  131.     m_rtsp_session = NULL;
  132.   }
  133.   
  134.   if (m_recv_thread) {
  135.     m_rtp_msg_queue.send_message(MSG_STOP_THREAD);
  136.     SDL_WaitThread(m_recv_thread, NULL);
  137.     m_recv_thread = NULL;
  138.   }
  139.   if (m_decode_thread) {
  140.     media_message(LOG_DEBUG, "decode thread %d", m_is_video);
  141.     m_decode_msg_queue.send_message(MSG_STOP_THREAD, 
  142.     NULL, 
  143.     0, 
  144.     m_decode_thread_sem);
  145.     SDL_WaitThread(m_decode_thread, NULL);
  146.     m_decode_thread = NULL;
  147.   }
  148.     
  149.   if (m_source_addr != NULL) free(m_source_addr);
  150.   m_next = NULL;
  151.   m_parent = NULL;
  152.   if (m_decode_thread_sem) {
  153.     SDL_DestroySemaphore(m_decode_thread_sem);
  154.     m_decode_thread_sem = NULL;
  155.   }
  156.   if (m_ports) {
  157.     delete m_ports;
  158.     m_ports = NULL;
  159.   }
  160.   if (m_rtp_byte_stream) {
  161.     double diff;
  162.     diff = difftime(time(NULL), m_start_time);
  163.     media_message(LOG_INFO, "Media %s", m_media_info->media);
  164.     
  165.     media_message(LOG_INFO, "Time: %g seconds", diff);
  166. #if 0
  167.     double div;
  168.     player_debug_message("Packets received: %u", m_rtp_packet_received);
  169.     player_debug_message("Payload received: "LLU" bytes", m_rtp_data_received);
  170.     div = m_rtp_packet_received / diff;
  171.     player_debug_message("Packets per sec : %g", div);
  172. #ifdef _WINDOWS
  173.     div = (int64_t)m_rtp_data_received;
  174. #else
  175. div = m_rtp_data_received;
  176. #endif
  177. div *= 8.0;
  178. div /= diff;
  179.     media_message(LOG_INFO, "Bits per sec   : %g", div);
  180. #endif
  181.  
  182.   }
  183.   if (m_byte_stream) {
  184.     delete m_byte_stream;
  185.     m_byte_stream = NULL;
  186.     m_rtp_byte_stream = NULL;
  187.   }
  188.   if (m_video_info) {
  189.     free(m_video_info);
  190.     m_video_info = NULL;
  191.   }
  192.   if (m_audio_info) {
  193.     free(m_audio_info);
  194.     m_audio_info = NULL;
  195.   }
  196.   if (m_user_data) {
  197.     free((void *)m_user_data);
  198.     m_user_data = NULL;
  199.   }
  200. }
  201. void CPlayerMedia::clear_rtp_packets (void)
  202. {
  203.   if (m_head != NULL) {
  204.     m_tail->rtp_next = NULL;
  205.     while (m_head != NULL) {
  206.       rtp_packet *p;
  207.       p = m_head;
  208.       m_head = m_head->rtp_next;
  209.       p->rtp_next = p->rtp_prev = NULL;
  210.       xfree(p);
  211.     }
  212.   }
  213.   m_tail = NULL;
  214.   m_rtp_queue_len = 0;
  215. }
  216. int CPlayerMedia::create_common (int is_video, char *errmsg, uint32_t errlen)
  217. {
  218.   m_parent->add_media(this);
  219.   m_is_video = is_video;
  220.   m_decode_thread_sem = SDL_CreateSemaphore(0);
  221.   m_decode_thread = SDL_CreateThread(c_decode_thread, this);
  222.   if (m_decode_thread_sem == NULL || m_decode_thread == NULL) {
  223.     const char *outmedia;
  224.     if (m_media_info == NULL) {
  225.       outmedia = m_is_video ? "video" : "audio";
  226.     } else outmedia = m_media_info->media;
  227.     if (errmsg != NULL)
  228.       snprintf(errmsg, errlen, "Couldn't start media thread for %s", 
  229.        outmedia);
  230.     media_message(LOG_ERR, "Failed to create decode thread for media %s",
  231.   outmedia);
  232.     return (-1);
  233.   }
  234.   return 0;
  235. }
  236. /*
  237.  * CPlayerMedia::create_from_file - create when we've already got a
  238.  * bytestream
  239.  */
  240. int CPlayerMedia::create_from_file (COurInByteStream *b, 
  241.     int is_video)
  242. {
  243.   m_byte_stream = b;
  244.   return create_common(is_video, NULL, 0);
  245. }
  246. /*
  247.  * CPlayerMedia::create_streaming - create a streaming media session,
  248.  * including setting up rtsp session, rtp and rtp bytestream
  249.  */
  250. int CPlayerMedia::create_streaming (media_desc_t *sdp_media,
  251.     char *errmsg,
  252.     uint32_t errlen,
  253.     int ondemand,
  254.     int use_rtsp,
  255.     int media_number_in_session)
  256. {
  257.   char buffer[80];
  258.   rtsp_command_t cmd;
  259.   rtsp_decode_t *decode;
  260.   
  261.   m_streaming = 1;
  262.   if (sdp_media == NULL) {
  263.     snprintf(errmsg, errlen, "Internal media error - sdp is NULL");
  264.     return(-1);
  265.   }
  266.   if (strncasecmp(sdp_media->proto, "RTP", strlen("RTP")) != 0) {
  267.     snprintf(errmsg, errlen, "Media %s doesn't use RTP", sdp_media->media);
  268.     media_message(LOG_ERR, "%s doesn't use RTP", sdp_media->media);
  269.     return (-1);
  270.   }
  271.   if (sdp_media->fmt == NULL) {
  272.     snprintf(errmsg, errlen, "Media %s doesn't have any usuable formats",
  273.      sdp_media->media);
  274.     media_message(LOG_ERR, "%s doesn't have any formats", 
  275.   sdp_media->media);
  276.     return (-1);
  277.   }
  278.   m_media_info = sdp_media;
  279.   m_stream_ondemand = ondemand;
  280.   if (ondemand != 0) {
  281.     /*
  282.      * Get 2 consecutive IP ports.  If we don't have this, don't even
  283.      * bother
  284.      */
  285.     if (use_rtsp == 0) {
  286.       m_ports = new C2ConsecIpPort(m_parent->get_unused_ip_port_ptr());
  287.       if (m_ports == NULL || !m_ports->valid()) {
  288. snprintf(errmsg, errlen, "Could not find any valid IP ports");
  289. media_message(LOG_ERR, "Couldn't get valid IP ports");
  290. return (-1);
  291.       }
  292.       m_our_port = m_ports->first_port();
  293.       /*
  294.        * Send RTSP setup message - first create the transport string for that
  295.        * message
  296.        */
  297.       create_rtsp_transport_from_sdp(m_parent->get_sdp_info(),
  298.      m_media_info,
  299.      m_our_port,
  300.      buffer,
  301.      sizeof(buffer));
  302.     } else {
  303.       m_rtp_use_rtsp = 1;
  304.       m_rtp_media_number_in_session = media_number_in_session;
  305.       snprintf(buffer, sizeof(buffer), "RTP/AVP/TCP;unicast;interleaved=%d-%d",
  306.        media_number_in_session * 2, (media_number_in_session * 2) + 1);
  307.     }
  308.     memset(&cmd, 0, sizeof(rtsp_command_t));
  309.     cmd.transport = buffer;
  310.     int err = 
  311.       rtsp_send_setup(m_parent->get_rtsp_client(),
  312.       m_media_info->control_string,
  313.       &cmd,
  314.       &m_rtsp_session,
  315.       &decode,
  316.       m_parent->session_control_is_aggregate());
  317.     if (err != 0) {
  318.       snprintf(errmsg, errlen, "Couldn't set up session %s", 
  319.        m_media_info->control_string);
  320.       media_message(LOG_ERR, "Can't create session %s - error code %d", 
  321.     m_media_info->media, err);
  322.       if (decode != NULL)
  323. free_decode_response(decode);
  324.       return (-1);
  325.     }
  326.     cmd.transport = NULL;
  327.     media_message(LOG_INFO, "Transport returned is %s", decode->transport);
  328.     /*
  329.      * process the transport they sent.  They need to send port numbers, 
  330.      * addresses, rtptime information, that sort of thing
  331.      */
  332.     if (process_rtsp_transport(decode->transport) != 0) {
  333.       snprintf(errmsg, errlen, "Couldn't process transport information in RTSP response: %s", decode->transport);
  334.       free_decode_response(decode);
  335.       return(-1);
  336.     }
  337.     free_decode_response(decode);
  338.   } else {
  339.     m_server_port = m_our_port = m_media_info->port;
  340.   }
  341.   connect_desc_t *cptr;
  342.   cptr = get_connect_desc_from_media(m_media_info);
  343.   if (cptr == NULL) {
  344.     snprintf(errmsg, errlen, "Server did not return address");
  345.     return (-1);
  346.   }
  347.   //
  348.   // okay - here we want to check that the server port is set up, and
  349.   // go ahead and init rtp, and the associated task
  350.   //
  351.   m_start_time = time(NULL);
  352.   if (create_common(strcmp(sdp_media->media, "video") == 0, 
  353.     errmsg, errlen) < 0) {
  354.     return -1;
  355.   }
  356.   if (ondemand == 0 || use_rtsp == 0) {
  357.     m_rtp_inited = 0;
  358.     m_recv_thread = SDL_CreateThread(c_recv_thread, this);
  359.     if (m_recv_thread == NULL) {
  360.       snprintf(errmsg, errlen, "Couldn't create media %s RTP recv thread",
  361.        m_media_info->media);
  362.       media_message(LOG_ERR, errmsg);
  363.       return (-1);
  364.     }
  365.     while (m_rtp_inited == 0) {
  366.       SDL_Delay(10);
  367.     }
  368.     if (m_rtp_session == NULL) {
  369.       snprintf(errmsg, errlen, "Could not start RTP - check debug log");
  370.       media_message(LOG_ERR, errmsg);
  371.       return (-1);
  372.     }
  373.   } else {
  374.     int ret;
  375.     ret = rtsp_thread_set_rtp_callback(m_parent->get_rtsp_client(),
  376.        c_rtp_packet_callback,
  377.        c_rtp_periodic,
  378.        m_rtp_media_number_in_session,
  379.        this);
  380.     if (ret < 0) {
  381.       snprintf(errmsg, errlen, "Can't setup TCP/RTP callback");
  382.       return -1;
  383.     }
  384.     ret = rtsp_thread_perform_callback(m_parent->get_rtsp_client(),
  385.        c_init_rtp_tcp,
  386.        this);
  387.     if (ret < 0) {
  388.       snprintf(errmsg, errlen,  "Can't init RTP in RTSP thread");
  389.       return -1;
  390.     }
  391.   }
  392.   if (m_rtp_session == NULL) {
  393.     snprintf(errmsg, errlen, "Couldn't create RTP session for media %s",
  394.      m_media_info->media);
  395.     media_message(LOG_ERR, errmsg);
  396.     return (-1);
  397.   }
  398.   return (0);
  399. }
  400. int CPlayerMedia::create_video_plugin (const codec_plugin_t *p,
  401.        format_list_t *sdp_media,
  402.        video_info_t *video,
  403.        const uint8_t *user_data,
  404.        uint32_t userdata_size)
  405. {
  406.   if (m_video_sync == NULL) {
  407.     m_video_sync = m_parent->set_up_video_sync();
  408.   }
  409.   if (m_video_sync == NULL) return -1;
  410.   m_plugin = p;
  411.   m_video_info = video;
  412.   m_plugin_data = (p->vc_create)(sdp_media,
  413.  video,
  414.  user_data,
  415.  userdata_size,
  416.  get_video_vft(),
  417.  m_video_sync);
  418.   if (m_plugin_data == NULL) 
  419.     return -1;
  420.   if (user_data != NULL) 
  421.     set_user_data(user_data, userdata_size);
  422.   return 0;
  423. }
  424. void CPlayerMedia::set_plugin_data (const codec_plugin_t *p, 
  425.     codec_data_t *d, 
  426.     video_vft_t *v, 
  427.     audio_vft_t *a)
  428. {
  429.   m_plugin = p;
  430.   m_plugin_data = d;
  431.   if (is_video()) {
  432.     if (m_video_sync == NULL) {
  433.       m_video_sync = m_parent->set_up_video_sync();
  434.     }
  435.     d->ifptr = m_video_sync;
  436.     d->v.video_vft = v;
  437.   } else {
  438.     if (m_audio_sync == NULL) {
  439.       m_audio_sync = m_parent->set_up_audio_sync();
  440.     }
  441.     d->ifptr = m_audio_sync;
  442.     d->v.audio_vft = a;
  443.   }
  444.     
  445. }
  446. int CPlayerMedia::get_plugin_status (char *buffer, uint32_t buflen)
  447. {
  448.   if (m_plugin == NULL) return -1;
  449.   if (m_plugin->c_print_status == NULL) return -1;
  450.   return ((m_plugin->c_print_status)(m_plugin_data, buffer, buflen));
  451. }
  452. int CPlayerMedia::create_audio_plugin (const codec_plugin_t *p,
  453.        format_list_t *sdp_media,
  454.        audio_info_t *audio,
  455.        const uint8_t *user_data,
  456.        uint32_t userdata_size)
  457. {
  458.   if (m_audio_sync == NULL) {
  459.     m_audio_sync = m_parent->set_up_audio_sync();
  460.   }
  461.   if (m_audio_sync == NULL) return -1;
  462.   m_audio_info = audio;
  463.   m_plugin = p;
  464.   m_plugin_data = (p->ac_create)(sdp_media,
  465.  audio,
  466.  user_data,
  467.  userdata_size,
  468.  get_audio_vft(),
  469.  m_audio_sync);
  470.   if (m_plugin_data == NULL) return -1;
  471.   if (user_data != NULL)
  472.     set_user_data(user_data, userdata_size);
  473.   return 0;
  474. }
  475. /*
  476.  * CPlayerMedia::do_play - get play command
  477.  */
  478. int CPlayerMedia::do_play (double start_time_offset)
  479. {
  480.   if (m_streaming != 0) {
  481.     if (m_stream_ondemand != 0) {
  482.       /*
  483.        * We're streaming - send the RTSP play command
  484.        */
  485.       if (m_parent->session_control_is_aggregate() == 0) {
  486. char buffer[80];
  487. rtsp_command_t cmd;
  488. rtsp_decode_t *decode;
  489. range_desc_t *range;
  490. memset(&cmd, 0, sizeof(rtsp_command_t));
  491. // only do range if we're not paused
  492. range = get_range_from_media(m_media_info);
  493. if (range == NULL) {
  494.   return (-1);
  495. }
  496. if (start_time_offset < range->range_start || 
  497.     start_time_offset > range->range_end) 
  498.   start_time_offset = range->range_start;
  499. // need to check for smpte
  500. sprintf(buffer, "npt=%g-%g", start_time_offset, range->range_end);
  501. cmd.range = buffer;
  502. if (rtsp_send_play(m_rtsp_session, &cmd, &decode) != 0) {
  503.   media_message(LOG_ERR, "RTSP play command failed");
  504.   free_decode_response(decode);
  505.   return (-1);
  506. }
  507. /*
  508.  * process the return information
  509.  */
  510. int ret = process_rtsp_rtpinfo(decode->rtp_info, m_parent, this);
  511. if (ret < 0) {
  512.   media_message(LOG_ERR, "rtsp rtpinfo failed");
  513.   free_decode_response(decode);
  514.   return (-1);
  515. }
  516. free_decode_response(decode);
  517.       }
  518.       if (m_source_addr == NULL) {
  519. // get the ip address of the server from the rtsp stack
  520. m_source_addr = strdup(inet_ntoa(get_server_ip_address(m_rtsp_session)));
  521. media_message(LOG_INFO, "Setting source address from rtsp - %s", 
  522.       m_source_addr);
  523.       }
  524.       // ASDF - probably need to do some stuff here for no rtpinfo...
  525.       /*
  526.        * set the various play times, and send a message to the recv task
  527.        * that it needs to start
  528.        */
  529.       m_play_start_time = start_time_offset;
  530.       if (m_rtp_byte_stream != NULL) {
  531. m_rtp_byte_stream->set_start_time((uint64_t)(start_time_offset * 1000.0));
  532.       }
  533.     }
  534.     m_paused = 0;
  535.     if (m_rtp_use_rtsp) {
  536.       rtsp_thread_perform_callback(m_parent->get_rtsp_client(),
  537.    c_rtp_start, 
  538.    this);
  539.     } else {
  540.       m_rtp_msg_queue.send_message(MSG_START_SESSION);
  541.     }
  542.   } else {
  543.     /*
  544.      * File (or other) playback.
  545.      */
  546.     if (m_paused == 0 || start_time_offset == 0.0) {
  547.       m_byte_stream->reset();
  548.     }
  549.     m_byte_stream->set_start_time((uint64_t)(start_time_offset * 1000.0));
  550.     m_play_start_time = start_time_offset;
  551.     m_paused = 0;
  552.     start_decoding();
  553.   }
  554.   return (0);
  555. }
  556. /*
  557.  * CPlayerMedia::do_pause - stop what we're doing
  558.  */
  559. int CPlayerMedia::do_pause (void)
  560. {
  561.   if (m_streaming != 0) {
  562.     if (m_stream_ondemand != 0) {
  563.       /*
  564.      * streaming - send RTSP pause
  565.      */
  566.       if (m_parent->session_control_is_aggregate() == 0) {
  567. rtsp_command_t cmd;
  568. rtsp_decode_t *decode;
  569. memset(&cmd, 0, sizeof(rtsp_command_t));
  570. if (rtsp_send_pause(m_rtsp_session, &cmd, &decode) != 0) {
  571.   media_message(LOG_ERR, "RTSP play command failed");
  572.   free_decode_response(decode);
  573.   return (-1);
  574. }
  575. free_decode_response(decode);
  576.       }
  577.     }
  578.     m_rtp_msg_queue.send_message(MSG_PAUSE_SESSION);
  579.     if (m_rtp_byte_stream) m_rtp_byte_stream->reset();
  580.   }
  581.   
  582.   /*
  583.    * Pause the various threads
  584.    */
  585.   m_decode_msg_queue.send_message(MSG_PAUSE_SESSION, 
  586.   NULL, 
  587.   0, 
  588.   m_decode_thread_sem);
  589.   m_paused = 1;
  590.   return (0);
  591. }
  592. double CPlayerMedia::get_max_playtime (void) 
  593. {
  594.   if (m_byte_stream) {
  595.     return (m_byte_stream->get_max_playtime());
  596.   }
  597.   return (0.0);
  598. }
  599. /***************************************************************************
  600.  * Transport and RTP-Info RTSP header line parsing.
  601.  ***************************************************************************/
  602. #define ADV_SPACE(a) {while (isspace(*(a)) && (*(a) != ''))(a)++;}
  603. #define TTYPE(a,b) {a, sizeof(a), b}
  604. static char *transport_parse_unicast (char *transport, CPlayerMedia *m)
  605. {
  606.   ADV_SPACE(transport);
  607.   if (*transport == '') return (transport);
  608.   if (*transport != ';')
  609.     return (NULL);
  610.   transport++;
  611.   ADV_SPACE(transport);
  612.   return (transport);
  613. }
  614. static char *transport_parse_multicast (char *transport, CPlayerMedia *m)
  615. {
  616.   media_message(LOG_ERR,"Received multicast indication during SETUP");
  617.   return (NULL);
  618. }
  619. static char *convert_number (char *transport, uint32_t &value)
  620. {
  621.   value = 0;
  622.   while (isdigit(*transport)) {
  623.     value *= 10;
  624.     value += *transport - '0';
  625.     transport++;
  626.   }
  627.   return (transport);
  628. }
  629. static char *convert_hex (char *transport, uint32_t &value)
  630. {
  631.   value = 0;
  632.   while (isxdigit(*transport)) {
  633.     value *= 16;
  634.     if (isdigit(*transport))
  635.       value += *transport - '0';
  636.     else
  637.       value += tolower(*transport) - 'a' + 10;
  638.     transport++;
  639.   }
  640.   return (transport);
  641. }
  642. static char *transport_parse_client_port (char *transport, CPlayerMedia *m)
  643. {
  644.   uint32_t port;
  645.   uint16_t our_port, our_port_max;
  646.   if (*transport++ != '=') {
  647.     return (NULL);
  648.   }
  649.   ADV_SPACE(transport);
  650.   transport = convert_number(transport, port);
  651.   ADV_SPACE(transport);
  652.   our_port = m->get_our_port();
  653.   our_port_max = our_port + 1;
  654.   if (port != our_port) {
  655.     media_message(LOG_ERR, "Returned client port %u doesn't match sent %u",
  656.   port, our_port);
  657.     return (NULL);
  658.   }
  659.   if (*transport == ';') {
  660.     transport++;
  661.     return (transport);
  662.   }
  663.   if (*transport == '') {
  664.     return (transport);
  665.   }
  666.   if (*transport != '-') {
  667.     return (NULL);
  668.   }
  669.   transport++;
  670.   ADV_SPACE(transport);
  671.   transport = convert_number(transport, port);
  672.   if ((port < our_port) || 
  673.       (port > our_port_max)) {
  674.     media_message(LOG_ERR, "Illegal client to port %u, range %u to %u",
  675.  port, our_port, our_port_max);
  676.     return (NULL);
  677.   }
  678.   ADV_SPACE(transport);
  679.   if (*transport == ';') {
  680.     transport++;
  681.   }
  682.   return(transport);
  683. }
  684. static char *transport_parse_server_port (char *transport, CPlayerMedia *m)
  685. {
  686.   uint32_t fromport, toport;
  687.   if (*transport++ != '=') {
  688.     return (NULL);
  689.   }
  690.   ADV_SPACE(transport);
  691.   transport = convert_number(transport, fromport);
  692.   ADV_SPACE(transport);
  693.   m->set_server_port((uint16_t)fromport);
  694.   if (*transport == ';') {
  695.     transport++;
  696.     return (transport);
  697.   }
  698.   if (*transport == '') {
  699.     return (transport);
  700.   }
  701.   if (*transport != '-') {
  702.     return (NULL);
  703.   }
  704.   transport++;
  705.   ADV_SPACE(transport);
  706.   transport = convert_number(transport, toport);
  707.   if (toport < fromport || toport > fromport + 1) {
  708.     media_message(LOG_ERR, "Illegal server to port %u, from is %u",
  709.  toport, fromport);
  710.     return (NULL);
  711.   }
  712.   ADV_SPACE(transport);
  713.   if (*transport == ';') {
  714.     transport++;
  715.   }
  716.   return(transport);
  717. }
  718. static char *transport_parse_source (char *transport, CPlayerMedia *m)
  719. {
  720.   char *ptr, *newone;
  721.   uint32_t addrlen;
  722.   if (*transport != '=') {
  723.     return (NULL);
  724.   }
  725.   transport++;
  726.   ADV_SPACE(transport);
  727.   ptr = transport;
  728.   while (*transport != ';' && *transport != '') transport++;
  729.   addrlen = transport - ptr;
  730.   if (addrlen == 0) {
  731.     return (NULL);
  732.   }
  733.   newone = (char *)malloc(addrlen + 1);
  734.   if (newone == NULL) {
  735.     media_message(LOG_ERR, "Can't alloc memory for transport source");
  736.     return (NULL);
  737.   }
  738.   strncpy(newone, ptr, addrlen);
  739.   newone[addrlen] = '';
  740.   m->set_source_addr(newone);
  741.   if (*transport == ';') transport++;
  742.   return (transport);
  743. }
  744. static char *transport_parse_ssrc (char *transport, CPlayerMedia *m)
  745. {
  746.   uint32_t ssrc;
  747.   if (*transport != '=') {
  748.     return (NULL);
  749.   }
  750.   transport++;
  751.   ADV_SPACE(transport);
  752.   transport = convert_hex(transport, ssrc);
  753.   ADV_SPACE(transport);
  754.   if (*transport != '') {
  755.     if (*transport != ';') {
  756.       return (NULL);
  757.     }
  758.     transport++;
  759.   }
  760.   m->set_rtp_ssrc(ssrc);
  761.   return (transport);
  762. }
  763. static char *transport_parse_interleave (char *transport, CPlayerMedia *m)
  764. {
  765.   uint32_t chan, chan2;
  766.   if (*transport != '=') {
  767.     return (NULL);
  768.   }
  769.   transport++;
  770.   ADV_SPACE(transport);
  771.   transport = convert_number(transport, chan);
  772.   chan2 = m->get_rtp_media_number() * 2;
  773.   if (chan != chan2) {
  774.     media_message(LOG_ERR, "Transport interleave not what was requested %d %d", 
  775.  chan, chan2);
  776.     return NULL;
  777.   }
  778.   ADV_SPACE(transport);
  779.   if (*transport != '') {
  780.     if (*transport != '-') {
  781.       return (NULL);
  782.     }
  783.     transport++;
  784.     transport = convert_number(transport, chan2);
  785.     if (chan + 1 != chan2) {
  786.       media_message(LOG_ERR, "Error in transport interleaved field");
  787.       return (NULL);
  788.     }
  789.     
  790.     if (*transport == '') return (transport);
  791.   }
  792.   if (*transport != ';') return (NULL);
  793.   transport++;
  794.   return (transport);
  795. }
  796. static char *rtpinfo_parse_ssrc (char *transport, CPlayerMedia *m, int &end)
  797. {
  798.   uint32_t ssrc;
  799.   if (*transport != '=') {
  800.     return (NULL);
  801.   }
  802.   transport++;
  803.   ADV_SPACE(transport);
  804.   transport = convert_hex(transport, ssrc);
  805.   ADV_SPACE(transport);
  806.   if (*transport != '') {
  807.     if (*transport == ',') {
  808.       end = 1;
  809.     } else if (*transport != ';') {
  810.       return (NULL);
  811.     }
  812.     transport++;
  813.   }
  814.   m->set_rtp_ssrc(ssrc);
  815.   return (transport);
  816. }
  817. static char *rtpinfo_parse_seq (char *rtpinfo, CPlayerMedia *m, int &endofurl)
  818. {
  819.   uint32_t seq;
  820.   if (*rtpinfo != '=') {
  821.     return (NULL);
  822.   }
  823.   rtpinfo++;
  824.   ADV_SPACE(rtpinfo);
  825.   rtpinfo = convert_number(rtpinfo, seq);
  826.   ADV_SPACE(rtpinfo);
  827.   if (*rtpinfo != '') {
  828.     if (*rtpinfo == ',') {
  829.       endofurl = 1;
  830.     } else if (*rtpinfo != ';') {
  831.       return (NULL);
  832.     }
  833.     rtpinfo++;
  834.   }
  835.   m->set_rtp_base_seq(seq);
  836.   return (rtpinfo);
  837. }
  838. static char *rtpinfo_parse_rtptime (char *rtpinfo, 
  839.     CPlayerMedia *m, 
  840.     int &endofurl)
  841. {
  842.   uint32_t rtptime;
  843.   int neg = 0;
  844.   if (*rtpinfo != '=') {
  845.     return (NULL);
  846.   }
  847.   rtpinfo++;
  848.   ADV_SPACE(rtpinfo);
  849.   if (*rtpinfo == '-') {
  850.     neg = 1;
  851.     rtpinfo++;
  852.     ADV_SPACE(rtpinfo);
  853.   }
  854.   rtpinfo = convert_number(rtpinfo, rtptime);
  855.   ADV_SPACE(rtpinfo);
  856.   if (*rtpinfo != '') {
  857.     if (*rtpinfo == ',') {
  858.       endofurl = 1;
  859.     } else if (*rtpinfo != ';') {
  860.       return (NULL);
  861.     }
  862.     rtpinfo++;
  863.   }
  864.   if (neg != 0) {
  865.     player_error_message("Warning - negative time returned in rtpinfo");
  866.     rtptime = 0 - rtptime;
  867.   }
  868.   m->set_rtp_base_ts(rtptime);
  869.   return (rtpinfo);
  870. }
  871. struct {
  872.   const char *name;
  873.   uint32_t namelen;
  874.   char *(*routine)(char *transport, CPlayerMedia *);
  875. } transport_types[] = 
  876. {
  877.   TTYPE("unicast", transport_parse_unicast),
  878.   TTYPE("multicast", transport_parse_multicast),
  879.   TTYPE("client_port", transport_parse_client_port),
  880.   TTYPE("server_port", transport_parse_server_port),
  881.   TTYPE("source", transport_parse_source),
  882.   TTYPE("ssrc", transport_parse_ssrc),
  883.   TTYPE("interleaved", transport_parse_interleave),
  884.   {NULL, 0, NULL},
  885. }; 
  886. int CPlayerMedia::process_rtsp_transport (char *transport)
  887. {
  888.   uint32_t protolen;
  889.   int ix;
  890.   if (transport == NULL) 
  891.     return (-1);
  892.   protolen = strlen(m_media_info->proto);
  893.   
  894.   if (strncasecmp(transport, m_media_info->proto, protolen) != 0) {
  895.     media_message(LOG_ERR, "transport %s doesn't match %s", transport, 
  896.  m_media_info->proto);
  897.     return (-1);
  898.   }
  899.   transport += protolen;
  900.   if (*transport == '/') {
  901.     transport++;
  902.     if (m_rtp_use_rtsp) {
  903.       if (strncasecmp(transport, "TCP", strlen("TCP")) != 0) {
  904. media_message(LOG_ERR, "Transport is not TCP");
  905. return (-1);
  906.       }
  907.       transport += strlen("TCP");
  908.     } else {
  909.       if (strncasecmp(transport, "UDP", strlen("UDP")) != 0) {
  910. media_message(LOG_ERR, "Transport is not UDP");
  911. return (-1);
  912.       }
  913.       transport += strlen("UDP");
  914.     }
  915.   }
  916.   if (*transport != ';') {
  917.     return (-1);
  918.   }
  919.   transport++;
  920.   do {
  921.     ADV_SPACE(transport);
  922.     for (ix = 0; transport_types[ix].name != NULL; ix++) {
  923.       if (strncasecmp(transport, 
  924.       transport_types[ix].name, 
  925.       transport_types[ix].namelen - 1) == 0) {
  926. transport += transport_types[ix].namelen - 1;
  927. ADV_SPACE(transport);
  928. transport = (transport_types[ix].routine)(transport, this);
  929. break;
  930.       }
  931.     }
  932.     if (transport_types[ix].name == NULL) {
  933.       media_message(LOG_INFO, "Illegal mime type in transport - skipping %s", 
  934.    transport);
  935.       while (*transport != ';' && *transport != '') transport++;
  936.       if (*transport != '') transport++;
  937.     }
  938.   } while (transport != NULL && *transport != '');
  939.   if (transport == NULL) {
  940.     return (-1);
  941.   }
  942.   return (0);
  943. }
  944. struct {
  945.   const char *name;
  946.   uint32_t namelen;
  947.   char *(*routine)(char *transport, CPlayerMedia *, int &end_for_url);
  948. } rtpinfo_types[] = 
  949. {
  950.   TTYPE("seq", rtpinfo_parse_seq),
  951.   TTYPE("rtptime", rtpinfo_parse_rtptime),
  952.   TTYPE("ssrc", rtpinfo_parse_ssrc),
  953.   {NULL, 0, NULL},
  954. };
  955. int process_rtsp_rtpinfo (char *rtpinfo, 
  956.   CPlayerSession *session,
  957.   CPlayerMedia *media)
  958. {
  959.   int ix;
  960.   CPlayerMedia *newmedia;
  961.   if (rtpinfo == NULL) 
  962.     return (0);
  963.   do {
  964.     int no_mimes = 0;
  965.     ADV_SPACE(rtpinfo);
  966.     if (strncasecmp(rtpinfo, "url", strlen("url")) != 0) {
  967.       media_message(LOG_ERR, "Url not found");
  968.       return (-1);
  969.     }
  970.     rtpinfo += strlen("url");
  971.     ADV_SPACE(rtpinfo);
  972.     if (*rtpinfo != '=') {
  973.       media_message(LOG_ERR, "Can't find = after url");
  974.       return (-1);
  975.     }
  976.     rtpinfo++;
  977.     ADV_SPACE(rtpinfo);
  978.     char *url = rtpinfo;
  979.     while (*rtpinfo != '' && *rtpinfo != ';' && *rtpinfo != ',') {
  980.       rtpinfo++;
  981.     }
  982.     if (*rtpinfo == '') {
  983.       no_mimes = 1;
  984.     } else {
  985.       if (*rtpinfo == ',') {
  986. no_mimes = 1;
  987.       }
  988.       *rtpinfo++ = '';
  989.     }
  990.     char *temp = url;
  991.     newmedia = session->rtsp_url_to_media(url);
  992.     if (newmedia == NULL) {
  993.       media_message(LOG_ERR, "Can't find media from %s", url);
  994.       return -1;
  995.     } else if (media != NULL && media != newmedia) {
  996.       media_message(LOG_ERR, "Url in rtpinfo does not match media %s", url);
  997.       return -1;
  998.     }
  999.     if (temp != url) 
  1000.       free(url);
  1001.     if (no_mimes == 0) {
  1002.     int endofurl = 0;
  1003.     do {
  1004.       ADV_SPACE(rtpinfo);
  1005.       for (ix = 0; rtpinfo_types[ix].name != NULL; ix++) {
  1006. if (strncasecmp(rtpinfo,
  1007. rtpinfo_types[ix].name, 
  1008. rtpinfo_types[ix].namelen - 1) == 0) {
  1009.   rtpinfo += rtpinfo_types[ix].namelen - 1;
  1010.   ADV_SPACE(rtpinfo);
  1011.   rtpinfo = (rtpinfo_types[ix].routine)(rtpinfo, newmedia, endofurl);
  1012.   break;
  1013. }
  1014.       }
  1015.       if (rtpinfo_types[ix].name == NULL) {
  1016. #if 1
  1017. media_message(LOG_INFO, "Unknown mime-type in RtpInfo - skipping %s", 
  1018.      rtpinfo);
  1019. #endif
  1020. while (*rtpinfo != ';' && *rtpinfo != '') rtpinfo++;
  1021. if (*rtpinfo != '') rtpinfo++;
  1022.       }
  1023.     } while (endofurl == 0 && rtpinfo != NULL && *rtpinfo != '');
  1024.     } 
  1025.     newmedia = NULL;
  1026.   } while (rtpinfo != NULL && *rtpinfo != '');
  1027.   if (rtpinfo == NULL) {
  1028.     return (-1);
  1029.   }
  1030.   return (1);
  1031. }
  1032. int CPlayerMedia::rtp_receive_packet (unsigned char interleaved, 
  1033.       struct rtp_packet *pak, 
  1034.       int len)
  1035. {
  1036.   int ret;
  1037.   if ((interleaved & 1) == 0) {
  1038.     ret = rtp_process_recv_data(m_rtp_session, 0, pak, len);
  1039.     if (ret < 0) {
  1040.       xfree(pak);
  1041.     }
  1042.   } else {
  1043.     uint8_t *pakbuf = (uint8_t *)pak;
  1044.     pakbuf += sizeof(rtp_packet_data);
  1045.     
  1046.     rtp_process_ctrl(m_rtp_session, pakbuf, len);
  1047.     xfree(pak);
  1048.     ret = 0;
  1049.   }
  1050.   return ret;
  1051. }
  1052. void CPlayerMedia::rtp_periodic (void)
  1053. {
  1054.   rtp_send_ctrl(m_rtp_session, 
  1055. m_rtp_byte_stream != NULL ? 
  1056. m_rtp_byte_stream->get_last_rtp_timestamp() : 0, 
  1057. NULL);
  1058.   rtp_update(m_rtp_session);
  1059.   if (m_rtp_byte_stream != NULL) {
  1060.     int ret = m_rtp_byte_stream->recv_task(m_decode_thread_waiting);
  1061.     if (ret > 0) {
  1062.       if (m_rtp_buffering == 0) {
  1063. m_rtp_buffering = 1;
  1064. start_decoding();
  1065.       } else {
  1066. bytestream_primed();
  1067.       }
  1068.     }
  1069.     return;
  1070.   }
  1071.   if (m_head != NULL) {
  1072.     /*
  1073.      * Make sure that the payload type is the same
  1074.      */
  1075.     if (m_head->rtp_pak_pt == m_tail->rtp_pak_pt) {
  1076.       if (m_rtp_queue_len > 10) { // 10 packets consecutive proto same
  1077. if (determine_payload_type_from_rtp() == FALSE) {
  1078.   clear_rtp_packets(); 
  1079. }
  1080.       }
  1081.     } else {
  1082.       clear_rtp_packets();
  1083.     }
  1084.   }
  1085. }
  1086. void CPlayerMedia::rtp_start (void)
  1087. {
  1088.   if (m_rtp_ssrc_set == TRUE) {
  1089.     rtp_set_my_ssrc(m_rtp_session, m_rtp_ssrc);
  1090.   } else {
  1091.     // For now - we'll set up not to wait for RTCP validation 
  1092.     // before indicating if rtp library should accept.
  1093.     rtp_set_option(m_rtp_session, RTP_OPT_WEAK_VALIDATION, FALSE);
  1094.     rtp_set_option(m_rtp_session, RTP_OPT_PROMISC, TRUE);
  1095.   }
  1096.   if (m_rtp_byte_stream != NULL) {
  1097.     //m_rtp_byte_stream->reset(); - gets called when pausing
  1098.     m_rtp_byte_stream->flush_rtp_packets();
  1099.   }
  1100.   m_rtp_buffering = 0;
  1101. }
  1102. void CPlayerMedia::rtp_end(void)
  1103. {
  1104.   if (m_rtp_session != NULL) {
  1105.     rtp_send_bye(m_rtp_session);
  1106.     rtp_done(m_rtp_session);
  1107.   }
  1108.   m_rtp_session = NULL;
  1109. }
  1110. int CPlayerMedia::rtcp_send_packet (uint8_t *buffer, int buflen)
  1111. {
  1112.   if (config.get_config_value(CONFIG_SEND_RTCP_IN_RTP_OVER_RTSP) != 0) {
  1113.     return rtsp_thread_send_rtcp(m_parent->get_rtsp_client(),
  1114.  m_rtp_media_number_in_session,
  1115.  buffer, 
  1116.  buflen);
  1117.   }
  1118.   return buflen;
  1119. }
  1120. /****************************************************************************
  1121.  * RTP receive routines
  1122.  ****************************************************************************/
  1123. int CPlayerMedia::recv_thread (void)
  1124. {
  1125.   struct timeval timeout;
  1126.   int retcode;
  1127.   CMsg *newmsg;
  1128.   int recv_thread_stop = 0;
  1129.   connect_desc_t *cptr;
  1130.   int receiving = 0;
  1131.   cptr = get_connect_desc_from_media(m_media_info);
  1132.   m_rtp_buffering = 0;
  1133.   if (m_stream_ondemand != 0) {
  1134.     /*
  1135.      * We need to free up the ports that we got before RTP tries to set 
  1136.      * them up, so we don't have any re-use conflicts.  There is a small
  1137.      * window here that they might get used...
  1138.      */
  1139.     delete m_ports; // free up the port numbers
  1140.     m_ports = NULL;
  1141.   }
  1142. #ifdef _WINDOWS
  1143.   WORD wVersionRequested;
  1144.   WSADATA wsaData;
  1145.   int ret;
  1146.  
  1147.   wVersionRequested = MAKEWORD( 2, 0 );
  1148.   
  1149.   ret = WSAStartup( wVersionRequested, &wsaData );
  1150.   if ( ret != 0 ) {
  1151.     abort();
  1152.   }
  1153. #endif
  1154.   double bw;
  1155.   if (find_rtcp_bandwidth_from_media(m_media_info, &bw) < 0) {
  1156.     bw = 5000.0;
  1157.   } else {
  1158.     media_message(LOG_DEBUG, "Using bw from sdp %g", bw);
  1159.   }
  1160.   m_rtp_session = rtp_init(m_source_addr == NULL ? 
  1161.    cptr->conn_addr : m_source_addr,
  1162.    m_our_port,
  1163.    m_server_port,
  1164.    cptr == NULL ? 1 : cptr->ttl, // need ttl here
  1165.    bw, // rtcp bandwidth ?
  1166.    c_recv_callback,
  1167.    (uint8_t *)this);
  1168.   if (m_rtp_session != NULL) {
  1169.     rtp_set_option(m_rtp_session, RTP_OPT_WEAK_VALIDATION, FALSE);
  1170.     rtp_set_option(m_rtp_session, RTP_OPT_PROMISC, TRUE);
  1171.   }
  1172.   m_rtp_inited = 1;
  1173.   
  1174.   while (recv_thread_stop == 0) {
  1175.     /*
  1176.      * See if we need to check for a state change - this will allow
  1177.      * changes to the rtp info, if required.
  1178.      */
  1179.     while ((newmsg = m_rtp_msg_queue.get_message()) != NULL) {
  1180.       switch (newmsg->get_value()) {
  1181.       case MSG_STOP_THREAD:
  1182. recv_thread_stop = 1;
  1183. continue;
  1184.       case MSG_START_SESSION:
  1185. if (m_rtp_session == NULL) {
  1186.   continue;
  1187. }
  1188. rtp_start();
  1189. receiving = 1;
  1190. break;
  1191.       case MSG_PAUSE_SESSION:
  1192. break;
  1193.       }
  1194.       delete newmsg;
  1195.     }
  1196.     if (receiving == 0) {
  1197.       SDL_Delay(50);
  1198.       continue;
  1199.     }
  1200.     while (receiving == 1 && recv_thread_stop == 0) {
  1201.       if ((newmsg = m_rtp_msg_queue.get_message()) != NULL) {
  1202. //player_debug_message("recv thread message %d", newmsg->get_value());
  1203. switch (newmsg->get_value()) {
  1204. case MSG_STOP_THREAD:
  1205.   recv_thread_stop = 1;
  1206.   break;
  1207. case MSG_START_SESSION:
  1208.   //media_message(LOG_ERR, "Got play when playing");
  1209.   break;
  1210. case MSG_PAUSE_SESSION:
  1211.   // Indicate that we need to restart the session.
  1212.   // But keep going...
  1213.   media_message(LOG_DEBUG, "calling rtp start from pause");
  1214.   rtp_start();
  1215.   break;
  1216. }
  1217. delete newmsg;
  1218. newmsg = NULL;
  1219.       }
  1220.       if (recv_thread_stop == 1) {
  1221. continue;
  1222.       }
  1223.       timeout.tv_sec = 0;
  1224.       timeout.tv_usec = 500000;
  1225.       retcode = rtp_recv(m_rtp_session, &timeout, 0);
  1226.       //      player_debug_message("rtp_recv return %d", retcode);
  1227.       // Run rtp periodic after each packet received or idle time.
  1228.       if (m_paused == 0)
  1229. rtp_periodic();
  1230.     }
  1231.   }
  1232.   /*
  1233.    * When we're done, send a bye, close up rtp, and go home
  1234.    */
  1235.   rtp_end();
  1236.   return (0);
  1237. }
  1238. #ifdef DROP_PAKS
  1239. static int dropcount = 0;
  1240. #endif
  1241. /*
  1242.  * CPlayerMedia::recv_callback - callback from RTP with valid data
  1243.  */
  1244. void CPlayerMedia::recv_callback (struct rtp *session, rtp_event *e)
  1245. {
  1246.   if (e == NULL) return;
  1247.   /*
  1248.    * If we're paused, just dump the packet.  Multicast case
  1249.    */
  1250.   if (m_paused != 0) {
  1251.     if (e->type == RX_RTP) {
  1252.       xfree(e->data);
  1253.       return;
  1254.     }
  1255.   }
  1256. #if DROP_PAKS
  1257.     if (e->type == RX_RTP && dropcount >= 50) {
  1258.       xfree((rtp_packet *)e->data);
  1259.       dropcount = 0;
  1260.       return;
  1261.     } else { 
  1262.       dropcount++;
  1263.     }
  1264. #endif
  1265.   if (m_rtp_byte_stream != NULL) {
  1266.     m_rtp_byte_stream->recv_callback(session, e);
  1267.     return;
  1268.   }
  1269.   switch (e->type) {
  1270.   case RX_RTP:
  1271.     /* regular rtp packet - add it to the queue */
  1272.     rtp_packet *rpak;
  1273.     rpak = (rtp_packet *)e->data;
  1274.     if (rpak->rtp_data_len == 0) {
  1275.       xfree(rpak);
  1276.     } else {
  1277.       add_rtp_packet_to_queue(rpak, &m_head, &m_tail);
  1278.       m_rtp_queue_len++;
  1279.     }
  1280.     break;
  1281.   case RX_SR:
  1282.     rtcp_sr *srpak;
  1283.     srpak = (rtcp_sr *)e->data;
  1284.     m_rtcp_ntp_frac = srpak->ntp_frac;
  1285.     m_rtcp_ntp_sec = srpak->ntp_sec;
  1286.     m_rtcp_rtp_ts = srpak->rtp_ts;
  1287.     m_rtcp_received = 1;
  1288.     break;
  1289.   default:
  1290. #if 0
  1291.     media_message(LOG_DEBUG, "Thread %u - Callback from rtp with %d %p", 
  1292.   SDL_ThreadID(),e->type, e->data);
  1293. #endif
  1294.     break;
  1295.   }
  1296. }
  1297. /*
  1298.  * determine_payload_type_from_rtp - determine with protocol we're dealing with
  1299.  * in the rtp session.  Set various calculations for the sync task, as well...
  1300.  */
  1301. int CPlayerMedia::determine_payload_type_from_rtp(void)
  1302. {
  1303.   char payload_type = (char)m_head->rtp_pak_pt, temp;
  1304.   format_list_t *fmt;
  1305.   uint64_t tickpersec;
  1306.   CRtpByteStreamBase *bs;
  1307.   fmt = m_media_info->fmt;
  1308.   while (fmt != NULL) {
  1309.     temp = atoi(fmt->fmt);
  1310.     if (temp == payload_type) {
  1311.       m_media_fmt = fmt;
  1312.       if (fmt->rtpmap != NULL) {
  1313. tickpersec = fmt->rtpmap->clock_rate;
  1314.       } else {
  1315. if (payload_type >= 96) {
  1316.   media_message(LOG_ERR, "Media %s, rtp payload type of %u, no rtp map",
  1317. m_media_info->media, payload_type);
  1318.   return (FALSE);
  1319. }
  1320. tickpersec = 90000;
  1321.       }
  1322.       bs = 
  1323. create_rtp_byte_stream_for_format(m_media_fmt,
  1324.   payload_type,
  1325.   m_stream_ondemand,
  1326.   tickpersec,
  1327.   &m_head,
  1328.   &m_tail,
  1329.   m_rtsp_base_seq_received, 
  1330.   m_rtp_base_seq,
  1331.   m_rtsp_base_ts_received,
  1332.   m_rtp_base_ts,
  1333.   m_rtcp_received,
  1334.   m_rtcp_ntp_frac,
  1335.   m_rtcp_ntp_sec,
  1336.   m_rtcp_rtp_ts);
  1337.       bs->set_start_time((uint64_t)(m_play_start_time * 1000.0));
  1338.       m_rtp_byte_stream = bs;
  1339.       m_byte_stream = m_rtp_byte_stream;
  1340. #if 1
  1341.       media_message(LOG_DEBUG, "media %s - rtp tps %u ntp per rtp ",
  1342.    m_media_info->media,
  1343.    m_rtptime_tickpersec);
  1344. #endif
  1345.       return (TRUE);
  1346.     }
  1347.     fmt = fmt->next;
  1348.   }
  1349.   return (FALSE);
  1350. }
  1351. /*
  1352.  * set up rtptime
  1353.  */
  1354. void CPlayerMedia::set_rtp_base_ts (uint32_t time)
  1355. {
  1356.   m_rtsp_base_ts_received = 1;
  1357.   m_rtp_base_ts = time;
  1358.   if (m_rtp_byte_stream != NULL) {
  1359.     m_rtp_byte_stream->set_rtp_base_ts(time);
  1360.   }
  1361. }
  1362. void CPlayerMedia::set_rtp_base_seq (uint16_t seq)
  1363. {
  1364.   m_rtsp_base_seq_received = 1; 
  1365.   m_rtp_base_seq = seq;
  1366.   if (m_rtp_byte_stream != NULL) {
  1367.     m_rtp_byte_stream->set_rtp_base_seq(seq);
  1368.   }
  1369. }
  1370. void CPlayerMedia::rtp_init_tcp (void) 
  1371. {
  1372.   connect_desc_t *cptr;
  1373.   cptr = get_connect_desc_from_media(m_media_info);
  1374.   m_rtp_session = rtp_init_extern_net(m_source_addr == NULL ? 
  1375.       cptr->conn_addr : m_source_addr,
  1376.       m_our_port,
  1377.       m_server_port,
  1378.       cptr->ttl,
  1379.       5000.0, // rtcp bandwidth ?
  1380.       c_recv_callback,
  1381.       c_rtcp_send_packet,
  1382.       (uint8_t *)this);
  1383.   rtp_set_option(m_rtp_session, RTP_OPT_WEAK_VALIDATION, FALSE);
  1384.   rtp_set_option(m_rtp_session, RTP_OPT_PROMISC, TRUE);
  1385.   m_rtp_inited = 1;
  1386. }
  1387. /* end player_media.cpp */