/*****************************************************************
 * gmerlin - a general purpose multimedia framework and applications
 *
 * Copyright (c) 2001 - 2012 Members of the Gmerlin project
 * gmerlin-general@lists.sourceforge.net
 * http://gmerlin.sourceforge.net
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * *****************************************************************/

#include <string.h>
#include "server.h"
#include <gmerlin/http.h>

#include <gavl/metatags.h>
// #include <gavl/compression.h>

#if 0
/* Table taken from ffmpeg (rtp.c) and adapted */
static const struct 
  {
  int pt;
  const char enc_name[6];
  gavf_stream_type_t type;
  gavl_codec_id_t codec_id;
  int clock_rate;
  int audio_channels;
  } 
payload_types[] = 
  {
    {0, "PCMU",     GAVF_STREAM_AUDIO,   GAVL_CODEC_ID_ULAW, 8000, 1},
//    {3, "GSM",      GAVF_STREAM_AUDIO,   GAVL_CODEC_ID_NONE, 8000, 1},
//    {4, "G723",     GAVF_STREAM_AUDIO,   AV_CODEC_ID_G723_1, 8000, 1},
//    {5, "DVI4",     GAVF_STREAM_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
//    {6, "DVI4",     GAVF_STREAM_AUDIO,   AV_CODEC_ID_NONE, 16000, 1},
//    {7, "LPC",      GAVF_STREAM_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
    {8, "PCMA",     GAVF_STREAM_AUDIO,   GAVL_CODEC_ID_ALAW, 8000, 1},
//    {9, "G722",     GAVF_STREAM_AUDIO,   AV_CODEC_ID_ADPCM_G722, 8000, 1},
//    {10, "L16",     GAVF_STREAM_AUDIO,   AV_CODEC_ID_PCM_S16BE, 44100, 2},
//    {11, "L16",     GAVF_STREAM_AUDIO,   AV_CODEC_ID_PCM_S16BE, 44100, 1},
//    {12, "QCELP",   GAVF_STREAM_AUDIO,   AV_CODEC_ID_QCELP, 8000, 1},
//    {13, "CN",      GAVF_STREAM_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
    {14, "MPA",     GAVF_STREAM_AUDIO,   GAVL_CODEC_ID_MP2, -1, -1},
    {14, "MPA",     GAVF_STREAM_AUDIO,   GAVL_CODEC_ID_MP3, -1, -1},
//    {15, "G728",    GAVF_STREAM_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
//    {16, "DVI4",    GAVF_STREAM_AUDIO,   AV_CODEC_ID_NONE, 11025, 1},
//    {17, "DVI4",    GAVF_STREAM_AUDIO,   AV_CODEC_ID_NONE, 22050, 1},
//    {18, "G729",    GAVF_STREAM_AUDIO,   AV_CODEC_ID_NONE, 8000, 1},
//    {25, "CelB",    GAVF_STREAM_VIDEO,   AV_CODEC_ID_NONE, 90000, -1},
    {26, "JPEG",    GAVF_STREAM_VIDEO,   GAVL_CODEC_ID_JPEG, 90000, -1},
//    {28, "nv",      GAVF_STREAM_VIDEO,   AV_CODEC_ID_NONE, 90000, -1},
//    {31, "H261",    GAVF_STREAM_VIDEO,   AV_CODEC_ID_H261, 90000, -1},
    {32, "MPV",     GAVF_STREAM_VIDEO,   GAVL_CODEC_ID_MPEG1, 90000, -1},
    {32, "MPV",     GAVF_STREAM_VIDEO,   GAVL_CODEC_ID_MPEG2, 90000, -1},
//    {33, "MP2T",    _DATA,    AV_CODEC_ID_MPEG2TS, 90000, -1},
//    {34, "H263",    _VIDEO,   AV_CODEC_ID_H263, 90000, -1},
    {-1 },
};

#define PT_PRIVATE 96

static int codec_id_2_pt(const gavf_stream_header_t * h, int idx)
  {
  int i = 0;
  while(payload_types[i].pt)
    {
    if((h->type == payload_types[i].type) &&
       (h->ci.id == payload_types[i].codec_id))
      {
      if(h->type == GAVF_STREAM_VIDEO)
        return payload_types[i].pt;
      else if(h->type == GAVF_STREAM_AUDIO)
        {
        if(((payload_types[i].clock_rate < 0) || (payload_types[i].clock_rate == h->format.audio.samplerate)) &&
           ((payload_types[i].audio_channels < 0) || (payload_types[i].audio_channels == h->format.audio.num_channels)))
          return payload_types[i].pt;
        }
      }
    }
  return PT_PRIVATE + idx;
  }
#endif // 0

static char * create_sdp_stream(const server_t * s,
                                const gavf_stream_header_t * h, int idx)
  {
  int success = 0;
  char * tmp_string;
  char * ret = NULL;
  
  switch(h->ci.id)
    {
    /* Audio */
    case GAVL_CODEC_ID_ALAW: //!< alaw 2:1
      if((h->format.audio.samplerate == 8000) &&
         (h->format.audio.num_channels == 1))
        {
        ret = bg_sprintf("m=audio 0 RTP/AVP 8\r\n"
                         "a=rtpmap:8 PCMA/8000/1\r\n");
        }
      break;
    case GAVL_CODEC_ID_ULAW:      //!< mu-law 2:1
      if((h->format.audio.samplerate == 8000) &&
         (h->format.audio.num_channels == 1))
        {
        ret = bg_sprintf("m=audio 0 RTP/AVP 0\r\n"
                         "a=rtpmap:0 PCMU/8000/1\r\n");
        }
      goto fail;
      break;
    case GAVL_CODEC_ID_MP2:       //!< MPEG-1 audio layer II
    case GAVL_CODEC_ID_MP3:       //!< MPEG-1/2 audio layer 3 CBR/VBR
      ret = bg_sprintf("m=audio 0 RTP/AVP 14\r\n"
                       "a=rtpmap:14 MPA/%d/%d\r\n",
                       h->format.audio.samplerate, h->format.audio.num_channels);
      break;
    case GAVL_CODEC_ID_AC3:       //!< AC3
    case GAVL_CODEC_ID_AAC:       //!< AAC as stored in quicktime/mp4
    case GAVL_CODEC_ID_VORBIS:    //!< Vorbis (segmented extradata and packets)
    case GAVL_CODEC_ID_FLAC:      //!< Flac (extradata contain a file header without comment and seektable)
    case GAVL_CODEC_ID_OPUS:      //!< Opus
    case GAVL_CODEC_ID_SPEEX:     //!< Speex
    case GAVL_CODEC_ID_DTS:
      goto fail;
      break;
    
    /* Video */
    case GAVL_CODEC_ID_JPEG: //!< JPEG image
    case GAVL_CODEC_ID_PNG:            //!< PNG image
    case GAVL_CODEC_ID_TIFF:           //!< TIFF image
    case GAVL_CODEC_ID_TGA:            //!< TGA image
    case GAVL_CODEC_ID_MPEG1:          //!< MPEG-1 video
    case GAVL_CODEC_ID_MPEG2:          //!< MPEG-2 video
    case GAVL_CODEC_ID_MPEG4_ASP:      //!< MPEG-4 ASP (a.k.a. Divx4)
    case GAVL_CODEC_ID_H264:           //!< H.264 (Annex B)
    case GAVL_CODEC_ID_THEORA:         //!< Theora (segmented extradata)
    case GAVL_CODEC_ID_DIRAC:          //!< Complete DIRAC frames, sequence end code appended to last packet
    case GAVL_CODEC_ID_DV:             //!< DV (several variants)
    case GAVL_CODEC_ID_VP8:            //!< VP8 (as used in webm)
    case GAVL_CODEC_ID_DIV3:

    /* Subtitle (some video codecs can handle subtitles also */
    case GAVL_CODEC_ID_DVDSUB: //!< DVD subtitles, palette is in header
      goto fail;
      break;
    case GAVL_CODEC_ID_NONE:
      goto fail;
      break;
    }
  
  success = 1;
  fail:
  if(!success)
    {
    if(ret)
      {
      free(ret);
      ret = NULL;
      }
    }

  if(ret)
    {
    tmp_string = bg_sprintf("a=control:streamid=%d\r\n", h->id);
    ret = gavl_strcat(ret, tmp_string);
    free(tmp_string);
    }
  return ret;
  }

char * create_sdp(const server_t * s, const gavf_program_header_t * ph,
                  const gavl_dictionary_t * req)
  {
  char host[BG_SOCKET_ADDR_STR_LEN];
  char * pos;
  char * tmp_string;
  char * ret = NULL;
  const char * addr_format = "IP4";
  const char * var;
  int version = 0;
  int session_id = 0;
  int num_sdp_streams = 0;
  int i;

  /* Obtain host address */
  bg_socket_address_to_string(bg_http_server_get_address(s->s), host);
  pos = strrchr(host, ':');
  if(pos)
    *pos = '\0';

  // Build sdp
  ret = gavl_strcat(ret, "v=0\r\n");
  
  // o=
  tmp_string = bg_sprintf("o=- %d %d IN %s %s\r\n",
                          session_id, version, addr_format, host);
  ret = gavl_strcat(ret, tmp_string);
  free(tmp_string);

  // s=
  var = gavl_dictionary_get_string(&ph->m, GAVL_META_STATION);
  if(!var)
    var = gavl_dictionary_get_string(&ph->m, GAVL_META_LABEL);
  if(!var)
    var = gavl_dictionary_get_string(&ph->m, GAVL_META_TITLE);
  if(!var)
    var = "";
   
  tmp_string = bg_sprintf("s=%s\r\n", var);
  ret = gavl_strcat(ret, tmp_string);
  free(tmp_string);

  // i=
  var = gavl_dictionary_get_string(&ph->m, GAVL_META_COMMENT);
  if(var)
    {
    tmp_string = bg_sprintf("i=%s\r\n", var);
    ret = gavl_strcat(ret, tmp_string);
    free(tmp_string);
    }

  // t=
  var = gavl_dictionary_get_string(&ph->m, GAVL_META_APPROX_DURATION);
  if(!var)
    ret = gavl_strcat(ret, "t=0 0\r\na=range:ntp=0-\r\n");

  tmp_string = bg_sprintf("a=control:%s\r\n", bg_http_request_get_path(req));
  ret = gavl_strcat(ret, tmp_string);
  free(tmp_string);
    
  // m=
  for(i = 0; i < ph->num_streams; i++)
    {
    tmp_string = create_sdp_stream(s, ph->streams + i, i);
    if(tmp_string)
      {
      ret = gavl_strcat(ret, tmp_string);
      free(tmp_string);
      num_sdp_streams++;
      }
    }
  
  fprintf(stderr, "Created sdp:\n%s", ret);
  
  return ret;
  }
