sgimb.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:15k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * sgimb.c: a meta demux to parse sgimb referrer files
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * $Id: f2d83a3baa6f43bb039fc7aae1e8cb0e07a0ed2f $
  6.  *
  7.  * Authors: Derk-Jan Hartman <hartman at videolan dot org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * This is a metademux for the Kasenna MediaBase metafile format.
  25.  * Kasenna MediaBase first returns this file when you are trying to access
  26.  * their MPEG streams (MIME: application/x-sgimb). Very few applications
  27.  * understand this format and the format is not really documented on the net.
  28.  * Following a typical MediaBase file. Notice the sgi prefix of all the elements.
  29.  * This stems from the fact that the MediaBase servers were first introduced by SGI?????.
  30.  *
  31.  * sgiNameServerHost=host.name.tld
  32.  *     Obvious: the host hosting this stream
  33.  * Stream="xdma://host.name.tld/demo/a_very_cool.mpg"
  34.  *     Not always present. xdma can be read as RTSP.
  35.  * sgiMovieName=/demo/a_very_cool.mpg
  36.  *     The path to the asset
  37.  * sgiAuxState=1|2
  38.  *     AuxState=2 is always Video On Demand (so not Scheduled)
  39.  *     Not present with Live streams
  40.  * sgiLiveFeed=True|False
  41.  *     Denounces if the stream is live or from assets (Canned?)
  42.  *     Live appears as a little sattelite dish in the web interface of Kasenna
  43.  * sgiFormatName=PARTNER_41_MPEG-4
  44.  *     The type of stream. One of:
  45.  *       PARTNER_41_MPEG-4 (RTSP MPEG-4 fully compliant)
  46.  *       MPEG1-Audio       (MP3 Audio streams in MPEG TS)
  47.  *       MPEG-1            (MPEG 1 A/V in MPEG TS)
  48.  *       MPEG-2            (MPEG 2 A/V in MPEG TS)
  49.  * sgiWidth=720
  50.  *     The width of the to be received stream. Only present if stream is not Live.
  51.  * sgiHeight=576
  52.  *     The height of the to be received stream. Only present if stream is not Live.
  53.  * sgiBitrate=1630208
  54.  *     The bitrate of the to be received stream. Only present if stream is not Live.
  55.  * sgiDuration=378345000
  56.  *     The duration of the to be received stream. Only present if stream is not Live.
  57.  * sgiQTFileBegin
  58.  * rtsptext
  59.  * rtsp://host.name.tld/demo/a_very_cool.mpg
  60.  * sgiQTFileEnd
  61.  *     Sometimes present. QT will recognize this as a RTSP reference file, if present.
  62.  * sgiApplicationName=MediaBaseURL
  63.  *     Beats me !! :)
  64.  * sgiElapsedTime=0
  65.  *     Time passed since the asset was started (resets for repeating non live assets?)
  66.  * sgiMulticastAddress=233.81.233.15
  67.  *     The multicast IP used for the Multicast feed.
  68.  *     Also defines if a stream is multicast or not. (blue dot in kasenna web interface)
  69.  * sgiMulticastPort=1234
  70.  *     The multicast port for the same Multicast feed.
  71.  * sgiPacketSize=16384
  72.  *     The packetsize of the UDP frames that Kasenna sends. They should have used a default
  73.  *     that is a multiple of 188 (TS frame size). Most networks don't support more than 1500 anyways.
  74.  *     Also, when you lose a frame of this size, imagecorruption is more likely then with smaller
  75.  *     frames.
  76.  * sgiServerVersion=6.1.2
  77.  *     Version of the server
  78.  * sgiRtspPort=554
  79.  *     TCP port used for RTSP communication
  80.  * AutoStart=True
  81.  *     Start playing automatically
  82.  * DeliveryService=cds
  83.  *     Simulcasted (scheduled unicast) content. (Green dot in Kasenna web interface)
  84.  * sgiShowingName=A nice name that everyone likes
  85.  *     A human readible descriptive title for this stream.
  86.  * sgiSid=2311
  87.  *     Looks like this is the ID of the scheduled asset?
  88.  * sgiUserAccount=pid=1724&time=1078527309&displayText=You%20are%20logged%20as%20guest&
  89.  *     User Authentication. Above is a default guest entry. Not required for RTSP communication.
  90.  * sgiUserPassword=
  91.  *     Password :)
  92.  *
  93.  *****************************************************************************/
  94. /*****************************************************************************
  95.  * Preamble
  96.  *****************************************************************************/
  97. #ifdef HAVE_CONFIG_H
  98. # include "config.h"
  99. #endif
  100. #include <vlc_common.h>
  101. #include <vlc_demux.h>
  102. #include "playlist.h"
  103. /*****************************************************************************
  104.  * Local prototypes
  105.  *****************************************************************************/
  106. #define MAX_LINE 1024
  107. struct demux_sys_t
  108. {
  109.     char        *psz_uri;       /* Stream= or sgiQTFileBegin rtsp link */
  110.     char        *psz_server;    /* sgiNameServerHost= */
  111.     char        *psz_location;  /* sgiMovieName= */
  112.     char        *psz_name;      /* sgiShowingName= */
  113.     char        *psz_user;      /* sgiUserAccount= */
  114.     char        *psz_password;  /* sgiUserPassword= */
  115.     char        *psz_mcast_ip;  /* sgiMulticastAddress= */
  116.     int         i_mcast_port;   /* sgiMulticastPort= */
  117.     int         i_packet_size;  /* sgiPacketSize= */
  118.     mtime_t     i_duration;     /* sgiDuration= */
  119.     int         i_port;         /* sgiRtspPort= */
  120.     int         i_sid;          /* sgiSid= */
  121.     bool  b_concert;      /* DeliveryService=cds */
  122.     bool  b_rtsp_kasenna; /* kasenna style RTSP */
  123. };
  124. static int Demux ( demux_t *p_demux );
  125. static int Control( demux_t *p_demux, int i_query, va_list args );
  126. /*****************************************************************************
  127.  * Activate: initializes m3u demux structures
  128.  *****************************************************************************/
  129. int Import_SGIMB( vlc_object_t * p_this )
  130. {
  131.     demux_t *p_demux = (demux_t *)p_this;
  132.     const uint8_t *p_peek;
  133.     int i_size;
  134.     /* Lets check the content to see if this is a sgi mediabase file */
  135.     i_size = stream_Peek( p_demux->s, &p_peek, MAX_LINE );
  136.     i_size -= sizeof("sgiNameServerHost=") - 1;
  137.     if ( i_size > 0 )
  138.     {
  139.         unsigned int i_len = sizeof("sgiNameServerHost=") - 1;
  140.         while ( i_size && strncasecmp( (char *)p_peek, "sgiNameServerHost=", i_len ) )
  141.         {
  142.             p_peek++;
  143.             i_size--;
  144.         }
  145.         if ( !strncasecmp( (char *)p_peek, "sgiNameServerHost=", i_len ) )
  146.         {
  147.             STANDARD_DEMUX_INIT_MSG( "using SGIMB playlist reader" );
  148.             p_demux->p_sys->psz_uri = NULL;
  149.             p_demux->p_sys->psz_server = NULL;
  150.             p_demux->p_sys->psz_location = NULL;
  151.             p_demux->p_sys->psz_name = NULL;
  152.             p_demux->p_sys->psz_user = NULL;
  153.             p_demux->p_sys->psz_password = NULL;
  154.             p_demux->p_sys->psz_mcast_ip = NULL;
  155.             p_demux->p_sys->i_mcast_port = 0;
  156.             p_demux->p_sys->i_packet_size = 0;
  157.             p_demux->p_sys->i_duration = 0;
  158.             p_demux->p_sys->i_port = 0;
  159.             p_demux->p_sys->i_sid = 0;
  160.             p_demux->p_sys->b_rtsp_kasenna = false;
  161.             p_demux->p_sys->b_concert = false;
  162.  
  163.             return VLC_SUCCESS;
  164.         }
  165.     }
  166.     return VLC_EGENERIC;
  167. }
  168. /*****************************************************************************
  169.  * Deactivate: frees unused data
  170.  *****************************************************************************/
  171. void Close_SGIMB( vlc_object_t *p_this )
  172. {
  173.     demux_t *p_demux = (demux_t*)p_this;
  174.     demux_sys_t *p_sys = p_demux->p_sys;
  175.     free( p_sys->psz_uri );
  176.     free( p_sys->psz_server );
  177.     free( p_sys->psz_location );
  178.     free( p_sys->psz_name );
  179.     free( p_sys->psz_user );
  180.     free( p_sys->psz_password );
  181.     free( p_sys->psz_mcast_ip );
  182.     free( p_demux->p_sys );
  183.     return;
  184. }
  185. static int ParseLine ( demux_t *p_demux, char *psz_line )
  186. {
  187.     char        *psz_bol;
  188.     demux_sys_t *p_sys = p_demux->p_sys;
  189.     psz_bol = psz_line;
  190.     /* Remove unnecessary tabs or spaces at the beginning of line */
  191.     while( *psz_bol == ' ' || *psz_bol == 't' ||
  192.            *psz_bol == 'n' || *psz_bol == 'r' )
  193.     {
  194.         psz_bol++;
  195.     }
  196.     if( !strncasecmp( psz_bol, "rtsp://", sizeof("rtsp://") - 1 ) )
  197.     {
  198.         /* We found the link, it was inside a sgiQTFileBegin */
  199.         free( p_sys->psz_uri );
  200.         p_sys->psz_uri = strdup( psz_bol );
  201.     }
  202.     else if( !strncasecmp( psz_bol, "Stream="", sizeof("Stream="") - 1 ) )
  203.     {
  204.         psz_bol += sizeof("Stream="") - 1;
  205.         if ( !psz_bol )
  206.             return 0;
  207.         char* psz_tmp = strrchr( psz_bol, '"' );
  208.         if( !psz_tmp )
  209.             return 0;
  210.         psz_tmp[0] = '';
  211.         /* We cheat around xdma. for some reason xdma links work different then rtsp */
  212.         if( !strncasecmp( psz_bol, "xdma://", sizeof("xdma://") - 1 ) )
  213.         {
  214.             psz_bol[0] = 'r';
  215.             psz_bol[1] = 't';
  216.             psz_bol[2] = 's';
  217.             psz_bol[3] = 'p';
  218.         }
  219.         free( p_sys->psz_uri );
  220.         p_sys->psz_uri = strdup( psz_bol );
  221.     }
  222.     else if( !strncasecmp( psz_bol, "sgiNameServerHost=", sizeof("sgiNameServerHost=") - 1 ) )
  223.     {
  224.         psz_bol += sizeof("sgiNameServerHost=") - 1;
  225.         free( p_sys->psz_server );
  226.         p_sys->psz_server = strdup( psz_bol );
  227.     }
  228.     else if( !strncasecmp( psz_bol, "sgiMovieName=", sizeof("sgiMovieName=") - 1 ) )
  229.     {
  230.         psz_bol += sizeof("sgiMovieName=") - 1;
  231.         free( p_sys->psz_location );
  232.         p_sys->psz_location = strdup( psz_bol );
  233.     }
  234.     else if( !strncasecmp( psz_bol, "sgiUserAccount=", sizeof("sgiUserAccount=") - 1 ) )
  235.     {
  236.         psz_bol += sizeof("sgiUserAccount=") - 1;
  237.         free( p_sys->psz_user );
  238.         p_sys->psz_user = strdup( psz_bol );
  239.     }
  240.     else if( !strncasecmp( psz_bol, "sgiUserPassword=", sizeof("sgiUserPassword=") - 1 ) )
  241.     {
  242.         psz_bol += sizeof("sgiUserPassword=") - 1;
  243.         free( p_sys->psz_password );
  244.         p_sys->psz_password = strdup( psz_bol );
  245.     }
  246.     else if( !strncasecmp( psz_bol, "sgiShowingName=", sizeof("sgiShowingName=") - 1 ) )
  247.     {
  248.         psz_bol += sizeof("sgiShowingName=") - 1;
  249.         free( p_sys->psz_name );
  250.         p_sys->psz_name = strdup( psz_bol );
  251.     }
  252.     else if( !strncasecmp( psz_bol, "sgiFormatName=", sizeof("sgiFormatName=") - 1 ) )
  253.     {
  254.         psz_bol += sizeof("sgiFormatName=") - 1;
  255.         if( strcasestr( psz_bol, "MPEG-4") == NULL ) /*not mpeg4 found in string */
  256.             p_sys->b_rtsp_kasenna = true;
  257.     }
  258.     else if( !strncasecmp( psz_bol, "sgiMulticastAddress=", sizeof("sgiMulticastAddress=") - 1 ) )
  259.     {
  260.         psz_bol += sizeof("sgiMulticastAddress=") - 1;
  261.         free( p_sys->psz_mcast_ip );
  262.         p_sys->psz_mcast_ip = strdup( psz_bol );
  263.     }
  264.     else if( !strncasecmp( psz_bol, "sgiMulticastPort=", sizeof("sgiMulticastPort=") - 1 ) )
  265.     {
  266.         psz_bol += sizeof("sgiMulticastPort=") - 1;
  267.         p_sys->i_mcast_port = (int) strtol( psz_bol, NULL, 0 );
  268.     }
  269.     else if( !strncasecmp( psz_bol, "sgiPacketSize=", sizeof("sgiPacketSize=") - 1 ) )
  270.     {
  271.         psz_bol += sizeof("sgiPacketSize=") - 1;
  272.         p_sys->i_packet_size = (int) strtol( psz_bol, NULL, 0 );
  273.     }
  274.     else if( !strncasecmp( psz_bol, "sgiDuration=", sizeof("sgiDuration=") - 1 ) )
  275.     {
  276.         psz_bol += sizeof("sgiDuration=") - 1;
  277.         p_sys->i_duration = (mtime_t) strtol( psz_bol, NULL, 0 );
  278.     }
  279.     else if( !strncasecmp( psz_bol, "sgiRtspPort=", sizeof("sgiRtspPort=") - 1 ) )
  280.     {
  281.         psz_bol += sizeof("sgiRtspPort=") - 1;
  282.         p_sys->i_port = (int) strtol( psz_bol, NULL, 0 );
  283.     }
  284.     else if( !strncasecmp( psz_bol, "sgiSid=", sizeof("sgiSid=") - 1 ) )
  285.     {
  286.         psz_bol += sizeof("sgiSid=") - 1;
  287.         p_sys->i_sid = (int) strtol( psz_bol, NULL, 0 );
  288.     }
  289.     else if( !strncasecmp( psz_bol, "DeliveryService=cds", sizeof("DeliveryService=cds") - 1 ) )
  290.     {
  291.         p_sys->b_concert = true;
  292.     }
  293.     else
  294.     {
  295.         /* This line isn't really important */
  296.         return 0;
  297.     }
  298.     return VLC_SUCCESS;
  299. }
  300. /*****************************************************************************
  301.  * Demux: reads and demuxes data packets
  302.  *****************************************************************************
  303.  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
  304.  *****************************************************************************/
  305. static int Demux ( demux_t *p_demux )
  306. {
  307.     demux_sys_t     *p_sys = p_demux->p_sys;
  308.     input_item_t    *p_child = NULL;
  309.     char            *psz_line;
  310.     INIT_PLAYLIST_STUFF;
  311.     while( ( psz_line = stream_ReadLine( p_demux->s ) ) )
  312.     {
  313.         ParseLine( p_demux, psz_line );
  314.         free( psz_line );
  315.     }
  316.     if( p_sys->psz_mcast_ip )
  317.     {
  318.         /* Definetly schedules multicast session */
  319.         /* We don't care if it's live or not */
  320.         free( p_sys->psz_uri );
  321.         if( asprintf( &p_sys->psz_uri, "udp://@" "%s:%i", p_sys->psz_mcast_ip, p_sys->i_mcast_port ) == -1 )
  322.         {
  323.             p_sys->psz_uri = NULL;
  324.             return -1;
  325.         }
  326.     }
  327.     if( p_sys->psz_uri == NULL )
  328.     {
  329.         if( p_sys->psz_server && p_sys->psz_location )
  330.         {
  331.             if( asprintf( &p_sys->psz_uri, "rtsp://" "%s:%i%s",
  332.                      p_sys->psz_server, p_sys->i_port > 0 ? p_sys->i_port : 554, p_sys->psz_location ) == -1 )
  333.             {
  334.                 p_sys->psz_uri = NULL;
  335.                 return -1;
  336.             }
  337.         }
  338.     }
  339.     if( p_sys->b_concert )
  340.     {
  341.         /* It's definetly a simulcasted scheduled stream */
  342.         /* We don't care if it's live or not */
  343.         if( p_sys->psz_uri == NULL )
  344.         {
  345.             msg_Err( p_demux, "no URI was found" );
  346.             return -1;
  347.         }
  348.         free( p_sys->psz_uri );
  349.         if( asprintf( &p_sys->psz_uri, "%s%%3FMeDiAbAsEshowingId=%d%%26MeDiAbAsEconcert%%3FMeDiAbAsE",
  350.                 p_sys->psz_uri, p_sys->i_sid ) == -1 )
  351.         {
  352.             p_sys->psz_uri = NULL;
  353.             return -1;
  354.         }
  355.     }
  356.     p_child = input_item_NewWithType( VLC_OBJECT(p_demux), p_sys->psz_uri,
  357.                       p_sys->psz_name ? p_sys->psz_name : p_sys->psz_uri,
  358.                       0, NULL, 0, p_sys->i_duration, ITEM_TYPE_NET );
  359.  
  360.     if( !p_child )
  361.     {
  362.         msg_Err( p_demux, "A valid playlistitem could not be created" );
  363.         return -1;
  364.     }
  365.     input_item_CopyOptions( p_current_input, p_child );
  366.     if( p_sys->i_packet_size && p_sys->psz_mcast_ip )
  367.     {
  368.         char *psz_option;
  369.         p_sys->i_packet_size += 1000;
  370.         if( asprintf( &psz_option, "mtu=%i", p_sys->i_packet_size ) != -1 )
  371.         {
  372.             input_item_AddOption( p_child, psz_option, VLC_INPUT_OPTION_TRUSTED );
  373.             free( psz_option );
  374.         }
  375.     }
  376.     if( !p_sys->psz_mcast_ip )
  377.         input_item_AddOption( p_child, "rtsp-caching=5000", VLC_INPUT_OPTION_TRUSTED );
  378.     if( !p_sys->psz_mcast_ip && p_sys->b_rtsp_kasenna )
  379.         input_item_AddOption( p_child, "rtsp-kasenna", VLC_INPUT_OPTION_TRUSTED );
  380.     input_item_AddSubItem( p_current_input, p_child );
  381.     vlc_gc_decref( p_child );
  382.     HANDLE_PLAY_AND_RELEASE
  383.     return 0; /* Needed for correct operation of go back */
  384. }
  385. static int Control( demux_t *p_demux, int i_query, va_list args )
  386. {
  387.     VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args);
  388.     return VLC_EGENERIC;
  389. }