Ejemplo n.º 1
0
static int icecast_internal_connect(t_channel *c, t_channel_outputstream *os,
                                    t_icecast *icecast,
                                    char *error, int errsize)
{
  ogg_packet header;
  ogg_packet header_comm;
  ogg_packet header_code;

  (void)c;
  (void)os;

  if (icecast->connected)
    return MSERV_SUCCESS;

  if (shout_open(icecast->shout) != SHOUTERR_SUCCESS) {
    snprintf(error, errsize, "icecast: failed opening connection: %s",
             shout_get_error(icecast->shout));
    goto failed;
  }
  mserv_log("Successfully connected to Icecast server '%s:%d'"
            " for mount '%s'",
            shout_get_host(icecast->shout), shout_get_port(icecast->shout),
            shout_get_mount(icecast->shout));
  icecast->connected = 1;
  vorbis_info_init(&icecast->vi);
  if (vorbis_encode_init(&icecast->vi, os->channels, 
                         os->samplerate, -1,
                         icecast->bitrate, -1) != 0) {
    snprintf(error, errsize, "icecast: failed to initialise vorbis engine");
    goto failed;
  }
  vorbis_comment_init(&icecast->vc);
  vorbis_comment_add_tag(&icecast->vc, "ENCODER", "mserv " VERSION);
  vorbis_analysis_init(&icecast->vd, &icecast->vi);
  vorbis_block_init(&icecast->vd, &icecast->vb);
  ogg_stream_init(&icecast->os, rand());
  vorbis_analysis_headerout(&icecast->vd, &icecast->vc,
                            &header, &header_comm, &header_code);
  ogg_stream_packetin(&icecast->os, &header);
  ogg_stream_packetin(&icecast->os, &header_comm);
  ogg_stream_packetin(&icecast->os, &header_code);
  for (;;) {
    if (ogg_stream_flush(&icecast->os, &icecast->og) == 0)
      break;
    if (shout_send(icecast->shout, icecast->og.header,
                   icecast->og.header_len) != SHOUTERR_SUCCESS ||
        shout_send(icecast->shout, icecast->og.body,
                   icecast->og.body_len) != SHOUTERR_SUCCESS) {
      snprintf(error, errsize, "icecast: failed to send starter to "
               "shout: %s", shout_get_error(icecast->shout));
      vorbis_block_clear(&icecast->vb);
      vorbis_dsp_clear(&icecast->vd);
      vorbis_info_clear(&icecast->vi);
      goto failed;
    }
  }
  return MSERV_SUCCESS;
failed:
  if (icecast->connected)
    shout_close(icecast->shout);
  icecast->connected = 0;
  return MSERV_FAILURE;
}
Ejemplo n.º 2
0
/* The main loop for each instance. Gets data passed to it from the stream
 * manager (which gets it from the input module), and streams it to the
 * specified server
 */
void *ices_instance_stream(void *arg)
{
	int ret, shouterr;
	ref_buffer *buffer;
	char *connip;
	stream_description *sdsc = arg;
	instance_t *stream = sdsc->stream;
	input_module_t *inmod = sdsc->input;
	int reencoding = (inmod->type == ICES_INPUT_VORBIS) && stream->encode;
	int encoding = (inmod->type == ICES_INPUT_PCM) && stream->encode;
    char *stream_name = NULL, *stream_genre = NULL, *stream_description = NULL;
    char *user = NULL;
	
	vorbis_comment_init(&sdsc->vc);

	sdsc->shout = shout_new();

	/* we only support the ice protocol and vorbis streams currently */
	shout_set_format(sdsc->shout, SHOUT_FORMAT_VORBIS);
	//shout_set_protocol(sdsc->shout, SHOUT_PROTOCOL_ICE);
	shout_set_protocol(sdsc->shout, SHOUT_PROTOCOL_HTTP);

    signal(SIGPIPE, signal_hup_handler);

	connip = malloc(16);
	if(!resolver_getip(stream->hostname, connip, 16))
	{
		LOG_ERROR1("Could not resolve hostname \"%s\"", stream->hostname);
		free(connip);
		stream->died = 1;
		return NULL;
	}

	if (!(shout_set_host(sdsc->shout, connip)) == SHOUTERR_SUCCESS) {
		LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
		free(connip);
		stream->died = 1;
		return NULL;
	}

	shout_set_port(sdsc->shout, stream->port);
	if (!(shout_set_password(sdsc->shout, stream->password)) == SHOUTERR_SUCCESS) {
		LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
		free(connip);
		stream->died = 1;
		return NULL;
	}
    if (stream->user)
        user = stream->user;
    else
        user = "******";

    if(shout_set_user(sdsc->shout, user) != SHOUTERR_SUCCESS) {
		LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
		free(connip);
		stream->died = 1;
		return NULL;
    }

	if (!(shout_set_agent(sdsc->shout, VERSIONSTRING)) == SHOUTERR_SUCCESS) {
		LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
		free(connip);
		stream->died = 1;
		return NULL;
	}

	if (!(shout_set_mount(sdsc->shout, stream->mount)) == SHOUTERR_SUCCESS) {
		LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
		free(connip);
		stream->died = 1;
		return NULL;
	}

	/* set the metadata for the stream */
    if(stream->stream_name)
        stream_name = stream->stream_name;
    else if (ices_config->stream_name)
        stream_name = ices_config->stream_name;

    if(stream->stream_description)
        stream_description = stream->stream_description;
    else if (ices_config->stream_description)
        stream_description = ices_config->stream_description;

    if(stream->stream_genre)
        stream_genre = stream->stream_genre;
    else if (ices_config->stream_genre)
        stream_genre = ices_config->stream_genre;

    if(stream_name)
		if (!(shout_set_name(sdsc->shout, stream_name)) == SHOUTERR_SUCCESS) {
			LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
			free(connip);
			stream->died = 1;
			return NULL;
		}
	if (stream_genre)
		if (!(shout_set_genre(sdsc->shout, stream_genre)) == SHOUTERR_SUCCESS) {
			LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
			free(connip);
			stream->died = 1;
			return NULL;
		}
	if (stream_description)
		if (!(shout_set_description(sdsc->shout, stream_description)) == SHOUTERR_SUCCESS) {
			LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
			free(connip);
			stream->died = 1;
			return NULL;
		}

    if(stream->downmix && encoding && stream->channels == 1) {
        stream->channels = 1;
        sdsc->downmix = downmix_initialise();
    }

    if(stream->resampleinrate && stream->resampleoutrate && encoding) {
        stream->samplerate = stream->resampleoutrate;
        sdsc->resamp = resample_initialise(stream->channels, 
                stream->resampleinrate, stream->resampleoutrate);
    }

	if(encoding)
	{
		if(inmod->metadata_update)
			inmod->metadata_update(inmod->internal, &sdsc->vc);
		sdsc->enc = encode_initialise(stream->channels, stream->samplerate,
				stream->managed, stream->min_br, stream->nom_br, stream->max_br,
                stream->quality, stream->serial++, &sdsc->vc);
        if(!sdsc->enc) {
            LOG_ERROR0("Failed to configure encoder");
		    stream->died = 1;
            return NULL; /* FIXME: probably leaking some memory here */
        }
	}
	else if(reencoding)
		sdsc->reenc = reencode_init(stream);

    if(stream->savefilename != NULL) 
    {
        stream->savefile = fopen(stream->savefilename, "wb");
        if(!stream->savefile)
            LOG_ERROR2("Failed to open stream save file %s: %s", 
                    stream->savefilename, strerror(errno));
        else
            LOG_INFO1("Saving stream to file %s", stream->savefilename);
    }

	if((shouterr = shout_open(sdsc->shout)) == SHOUTERR_SUCCESS)
	{
		LOG_INFO3("Connected to server: %s:%d%s", 
				shout_get_host(sdsc->shout), shout_get_port(sdsc->shout), shout_get_mount(sdsc->shout));

		while(1)
		{
			if(stream->buffer_failures > MAX_ERRORS)
			{
				LOG_WARN0("Too many errors, shutting down");
				break;
			}

			buffer = stream_wait_for_data(stream);

			/* buffer being NULL means that either a fatal error occured,
			 * or we've been told to shut down
			 */
			if(!buffer)
				break;

			/* If data is NULL or length is 0, we should just skip this one.
			 * Probably, we've been signalled to shut down, and that'll be
			 * caught next iteration. Add to the error count just in case,
			 * so that we eventually break out anyway 
			 */
			if(!buffer->buf || !buffer->len)
			{
				LOG_WARN0("Bad buffer dequeued!");
				stream->buffer_failures++;
				continue; 
			}

            if(stream->wait_for_critical)
            {
                LOG_INFO0("Trying restart on new substream");
                stream->wait_for_critical = 0;
            }

            ret = process_and_send_buffer(sdsc, buffer);

            /* No data produced, do nothing */
            if(ret == -1)
                ;
            /* Fatal error */
            else if(ret == -2)
            {
                LOG_ERROR0("Serious error, waiting to restart on "
                           "next substream. Stream temporarily suspended.");
                /* Set to wait until a critical buffer comes through (start of
                 * a new substream, typically), and flush existing queue.
                 */
                thread_mutex_lock(&ices_config->flush_lock);
                stream->wait_for_critical = 1;
                input_flush_queue(stream->queue, 0);
                thread_mutex_unlock(&ices_config->flush_lock);
            }
            /* Non-fatal shout error */
            else if(ret == 0)
			{
				LOG_ERROR2("Send error: %s (%s)", 
                        shout_get_error(sdsc->shout), strerror(errno));
				if(shout_get_errno(sdsc->shout) == SHOUTERR_SOCKET)
				{
					int i=0;

					/* While we're trying to reconnect, don't receive data
					 * to this instance, or we'll overflow once reconnect
					 * succeeds
					 */
					thread_mutex_lock(&ices_config->flush_lock);
					stream->skip = 1;

					/* Also, flush the current queue */
					input_flush_queue(stream->queue, 1);
					thread_mutex_unlock(&ices_config->flush_lock);
					
					while((i < stream->reconnect_attempts ||
							stream->reconnect_attempts==-1) && 
                            !ices_config->shutdown)
					{
						i++;
						LOG_WARN0("Trying reconnect after server socket error");
						shout_close(sdsc->shout);
						if((shouterr = shout_open(sdsc->shout)) == SHOUTERR_SUCCESS)
						{
							LOG_INFO3("Connected to server: %s:%d%s", 
                                    shout_get_host(sdsc->shout), shout_get_port(sdsc->shout), 
                                    shout_get_mount(sdsc->shout));
                            /* This stream can't restart until the next
                             * logical stream comes along, since the
                             * server won't have any cached headers for
                             * this source/connection. So, don't continue
                             * yet.
                             */
                            thread_mutex_lock(&ices_config->flush_lock);
                            stream->wait_for_critical = 1;
                            input_flush_queue(stream->queue, 0);
                            thread_mutex_unlock(&ices_config->flush_lock);
							break;
						}
						else
						{
							LOG_ERROR3("Failed to reconnect to %s:%d (%s)",
								shout_get_host(sdsc->shout),shout_get_port(sdsc->shout),
								shout_get_error(sdsc->shout));
							if(i==stream->reconnect_attempts)
							{
								LOG_ERROR0("Reconnect failed too many times, "
										  "giving up.");
                                /* We want to die now */
								stream->buffer_failures = MAX_ERRORS+1; 
							}
							else /* Don't try again too soon */
								sleep(stream->reconnect_delay); 
						}
					}
					stream->skip = 0;
				}
				stream->buffer_failures++;
			}
			stream_release_buffer(buffer);
		}
	}
	else
	{
		LOG_ERROR3("Failed initial connect to %s:%d (%s)", 
				shout_get_host(sdsc->shout),shout_get_port(sdsc->shout), shout_get_error(sdsc->shout));
	}
	
	shout_close(sdsc->shout);

    if(stream->savefile != NULL) 
        fclose(stream->savefile);

    shout_free(sdsc->shout);
	encode_clear(sdsc->enc);
	reencode_clear(sdsc->reenc);
    downmix_clear(sdsc->downmix);
    resample_clear(sdsc->resamp);
	vorbis_comment_clear(&sdsc->vc);

	stream->died = 1;
	return NULL;
}
Ejemplo n.º 3
0
void QEncoder::stream()
{
  if (!m_streaming)
  {
    m_streaming = true;
    m_enc=new OggTheoraEncoder();
    m_enc->video_quality = m_Vquality->text().toInt();
    m_enc->video_bitrate = m_Vbitrate->text().toInt();
    if (m_Qfreej->IsAudioOn())
    {
      m_Qjack = m_Qfreej->getQjack();
      if (m_enc->audio = m_Qjack->getAudio())
      {
	m_enc->use_audio = true;
	(m_Qjack->getJack())->isEncoded(false);
	m_enc->audio_quality = m_Aquality->text().toInt();
// 	m_enc->audio_bitrate = m_Abitrate->text().toInt();
      }
    }
    else
      m_enc->audio = NULL;

    if (m_dumpButton->isChecked())
    {
      m_enc->set_filedump(m_FileName->text().toAscii());
    }
    if (m_IceButton->isChecked())
    {
      if(shout_set_host(m_enc->ice, m_Host->text().toAscii()))
	qDebug() << "shout_set_host: " << shout_get_error(m_enc->ice);

      if(shout_set_port(m_enc->ice, m_Port->text().toInt()))
	qDebug() << "shout_set_port: " << shout_get_error(m_enc->ice);

      if(shout_set_name(m_enc->ice, m_ShoutName->text().toAscii()))
	qDebug() << "shout_set_title: " << shout_get_error(m_enc->ice);

      if(shout_set_user(m_enc->ice, m_User->text().toAscii()))
	qDebug() << "shout_set_user: "******"shout_set_pass: "******"shout_set_mount: " << shout_get_error(m_enc->ice);
      if(shout_open(m_enc->ice) == SHOUTERR_SUCCESS) {
	qDebug() << "streaming on url: http://" << shout_get_host(m_enc->ice) << ":" \
	    << shout_get_port(m_enc->ice) <<  shout_get_mount(m_enc->ice);
	m_enc->write_to_stream = true;
      } else {
	qDebug() << "error connecting to server " << shout_get_host(m_enc->ice) << ":" \
	    << shout_get_error(m_enc->ice);
	m_enc->write_to_stream = false;
      }
    }
    m_freej->add_encoder(m_enc);	//also calls the OggTheoraEncoder::init method
    if (m_enc->audio)
    {
      m_enc->audio->Jack->isEncoded(true);	//starts to fill the audio encoder ring buffer
      QString val;
      val.setNum(m_enc->getAvBitRate(), 10);
      m_Abitrate->setText(val);
    }
    m_enc->active = true;
    m_streamButton->setText("Close to STOP");
    pollerRate->start(2000);
  }
  else
  {
    m_streaming = false;
    m_enc->stop();
    m_enc->active = false;
    deleteLater();
  }
}