Пример #1
0
void Rtmp::sendTag(FlvTag &tag)
{
     if( ! RTMP_IsConnected(m_rtmp) || RTMP_IsTimedout(m_rtmp) )
     {
        qDebug() << "RTMP error";
        exit(0);
     }

     RTMP_Write(m_rtmp,tag.constData(),tag.size());

     // Handle RTMP ping and such
     fd_set sockset; struct timeval timeout = {0,0};
     FD_ZERO(&sockset); FD_SET(RTMP_Socket(m_rtmp), &sockset);
     register int result = select(RTMP_Socket(m_rtmp) + 1, &sockset, NULL, NULL, &timeout);
     if (result == 1 && FD_ISSET(RTMP_Socket(m_rtmp), &sockset) )
     {
//         qDebug() << "RTMP_ReadPacket";
         RTMP_ReadPacket(m_rtmp, &m_rtmpPacket);
        if( ! RTMPPacket_IsReady(&m_rtmpPacket) )
        {
            qDebug() << "Received RTMP packet";
            RTMP_ClientPacket(m_rtmp,&m_rtmpPacket);
            RTMPPacket_Free(&m_rtmpPacket);
        }
    }
}
Пример #2
0
static int send_packet(struct rtmp_stream *stream,
		struct encoder_packet *packet, bool is_header, size_t idx)
{
	uint8_t *data;
	size_t  size;
	int     recv_size = 0;
	int     ret = 0;

#ifdef _WIN32
	ret = ioctlsocket(stream->rtmp.m_sb.sb_socket, FIONREAD,
			(u_long*)&recv_size);
#else
	ret = ioctl(stream->rtmp.m_sb.sb_socket, FIONREAD, &recv_size);
#endif

	if (ret >= 0 && recv_size > 0) {
		if (!discard_recv_data(stream, (size_t)recv_size))
			return -1;
	}

	flv_packet_mux(packet, &data, &size, is_header);
#ifdef TEST_FRAMEDROPS
	os_sleep_ms(rand() % 40);
#endif
	ret = RTMP_Write(&stream->rtmp, (char*)data, (int)size, (int)idx);
	bfree(data);

	obs_free_encoder_packet(packet);

	stream->total_bytes_sent += size;
	return ret;
}
Пример #3
0
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
{
    LibRTMPContext *ctx = s->priv_data;
    RTMP *r = &ctx->rtmp;

    return RTMP_Write(r, buf, size);
}
Пример #4
0
static GstFlowReturn
gst_rtmp_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstRTMPSink *sink = GST_RTMP_SINK (bsink);
  GstBuffer *reffed_buf = NULL;

  if (sink->first) {
    /* open the connection */
    if (!RTMP_IsConnected (sink->rtmp)) {
      if (!RTMP_Connect (sink->rtmp, NULL)
          || !RTMP_ConnectStream (sink->rtmp, 0)) {
        GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
            ("Could not connect to RTMP stream \"%s\" for writing", sink->uri));
        RTMP_Free (sink->rtmp);
        sink->rtmp = NULL;
        g_free (sink->rtmp_uri);
        sink->rtmp_uri = NULL;
        return GST_FLOW_ERROR;
      }
      GST_DEBUG_OBJECT (sink, "Opened connection to %s", sink->rtmp_uri);
    }

    /* FIXME: Parse the first buffer and see if it contains a header plus a packet instead
     * of just assuming it's only the header */
    GST_LOG_OBJECT (sink, "Caching first buffer of size %d for concatenation",
        GST_BUFFER_SIZE (buf));
    gst_buffer_replace (&sink->cache, buf);
    sink->first = FALSE;
    return GST_FLOW_OK;
  }

  if (sink->cache) {
    GST_LOG_OBJECT (sink, "Joining 2nd buffer of size %d to cached buf",
        GST_BUFFER_SIZE (buf));
    gst_buffer_ref (buf);
    reffed_buf = buf = gst_buffer_join (sink->cache, buf);
    sink->cache = NULL;
  }

  GST_LOG_OBJECT (sink, "Sending %d bytes to RTMP server",
      GST_BUFFER_SIZE (buf));

  if (!RTMP_Write (sink->rtmp,
          (char *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf))) {
    GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), ("Failed to write data"));
    if (reffed_buf)
      gst_buffer_unref (reffed_buf);
    return GST_FLOW_ERROR;
  }

  if (reffed_buf)
    gst_buffer_unref (reffed_buf);

  return GST_FLOW_OK;
}
Пример #5
0
static void send_meta_data(struct rtmp_stream *stream)
{
	uint8_t *meta_data;
	size_t  meta_data_size;

	flv_meta_data(stream->output, &meta_data, &meta_data_size);
#ifdef FILE_TEST
	fwrite(meta_data, 1, meta_data_size, stream->test);
#else
	RTMP_Write(&stream->rtmp, (char*)meta_data, (int)meta_data_size);
#endif
	bfree(meta_data);
}
Пример #6
0
static ssize_t rtmp_send(struct connectdata *conn, int sockindex,
                         const void *buf, size_t len, CURLcode *err)
{
    RTMP *r = conn->proto.generic;
    ssize_t num;

    (void)sockindex; /* unused */

    num = RTMP_Write(r, (char *)buf, curlx_uztosi(len));
    if(num < 0)
        *err = CURLE_SEND_ERROR;

    return num;
}
Пример #7
0
static bool send_meta_data(struct rtmp_stream *stream, size_t idx)
{
	uint8_t *meta_data;
	size_t  meta_data_size;
	bool success = flv_meta_data(stream->output, &meta_data,
			&meta_data_size, false, idx);

	if (success) {
		RTMP_Write(&stream->rtmp, (char*)meta_data,
				(int)meta_data_size, (int)idx);
		bfree(meta_data);
	}

	return success;
}
Пример #8
0
static int send_packet(struct rtmp_stream *stream,
		struct encoder_packet *packet, bool is_header)
{
	uint8_t *data;
	size_t  size;
	int     ret = 0;

	flv_packet_mux(packet, &data, &size, is_header);
#ifdef FILE_TEST
	fwrite(data, 1, size, stream->test);
#else
	ret = RTMP_Write(&stream->rtmp, (char*)data, (int)size);
#endif
	bfree(data);

	obs_free_encoder_packet(packet);
	return ret;
}
Пример #9
0
static int send_packet(struct rtmp_stream *stream,
		struct encoder_packet *packet, bool is_header, size_t idx)
{
	uint8_t *data;
	size_t  size;
	int     ret = 0;

	flv_packet_mux(packet, &data, &size, is_header);
#ifdef TEST_FRAMEDROPS
	os_sleep_ms(rand() % 40);
#endif
	ret = RTMP_Write(&stream->rtmp, (char*)data, (int)size, (int)idx);
	bfree(data);

	obs_free_encoder_packet(packet);

	stream->total_bytes_sent += size;
	return ret;
}
Пример #10
0
static GstFlowReturn
gst_rtmp_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstRTMPSink *sink = GST_RTMP_SINK (bsink);
  GstBuffer *reffed_buf = NULL;

  if (sink->first) {
    /* FIXME: Parse the first buffer and see if it contains a header plus a packet instead
     * of just assuming it's only the header */
    GST_LOG_OBJECT (sink, "Caching first buffer of size %d for concatenation",
        GST_BUFFER_SIZE (buf));
    gst_buffer_replace (&sink->cache, buf);
    sink->first = FALSE;
    return GST_FLOW_OK;
  }

  if (sink->cache) {
    GST_LOG_OBJECT (sink, "Joining 2nd buffer of size %d to cached buf",
        GST_BUFFER_SIZE (buf));
    gst_buffer_ref (buf);
    reffed_buf = buf = gst_buffer_join (sink->cache, buf);
    sink->cache = NULL;
  }

  GST_LOG_OBJECT (sink, "Sending %d bytes to RTMP server",
      GST_BUFFER_SIZE (buf));

  if (!RTMP_Write (sink->rtmp,
          (char *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf))) {
    GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), ("Failed to write data"));
    if (reffed_buf)
      gst_buffer_unref (reffed_buf);
    return GST_FLOW_ERROR;
  }

  if (reffed_buf)
    gst_buffer_unref (reffed_buf);

  return GST_FLOW_OK;
}
Пример #11
0
void RTMPWriter::write(uint8_t* data, size_t nbytes) {

  if(state == RW_STATE_NONE) {
    printf("error: cannot write to rtmp server because we haven't been initialized. did you call initialize()?\n");
    return;
  }
  else if(state == RW_STATE_RECONNECTING) {
    //printf("reconnecting... ignoring data...\n");
    return;
  }
  else if(state == RW_STATE_DISCONNECTED) {
    // the caller needs to call reconnect() 
    return;
  }
  
  //printf("rtmp: %ld\n", nbytes);
  int r = RTMP_Write(rtmp, (const char*)data, (int)nbytes);
  if(r < 0) {

    // @todo - we should close and cleanup here!!!!
    RTMP_Close(rtmp);
    RTMP_Free(rtmp);
    rtmp = NULL;

    printf("error: something went wrong while trying to write data to the rtmp server.\n");
    if(state == RW_STATE_DISCONNECTED) {
      return;
    }
    // when initialized and we arrive here, it means we're disconnected
    else if(state == RW_STATE_INITIALIZED) {

      state = RW_STATE_DISCONNECTED;
      if(cb_disconnect) {
        cb_disconnect(this, cb_user);
      }

    }
  }
}
Пример #12
0
static int send_packet(struct rtmp_stream *stream,
		struct encoder_packet *packet, bool is_header, size_t idx)
{
	uint8_t *data;
	size_t  size;
	int     recv_size = 0;
	int     ret = 0;

	if (!stream->new_socket_loop) {
#ifdef _WIN32
		ret = ioctlsocket(stream->rtmp.m_sb.sb_socket, FIONREAD,
				(u_long*)&recv_size);
#else
		ret = ioctl(stream->rtmp.m_sb.sb_socket, FIONREAD, &recv_size);
#endif

		if (ret >= 0 && recv_size > 0) {
			if (!discard_recv_data(stream, (size_t)recv_size))
				return -1;
		}
	}

	flv_packet_mux(packet, &data, &size, is_header);

#ifdef TEST_FRAMEDROPS
	droptest_cap_data_rate(stream, size);
#endif

	ret = RTMP_Write(&stream->rtmp, (char*)data, (int)size, (int)idx);
	bfree(data);

	if (is_header)
		bfree(packet->data);
	else
		obs_encoder_packet_release(packet);

	stream->total_bytes_sent += size;
	return ret;
}
Пример #13
0
int RTMP_Send_packet(RTMP_Packet *pkt)
{
	uint8_t pkt_header[18] = {0};	//根据协议文档,header 最大为14个字节
	uint8_t *p = pkt_header;

	if (pkt->fmt_type > 3)
	{
		printf("[RTMP_Send_packet] pkt fmt type error, fmt_type %d\n", pkt->fmt_type);
		return -1;
	}

	/*
		0 1 2 3 4 5 6 7
		+-+-+-+-+-+-+-+-+
		|fmt| cs id		|
		+-+-+-+-+-+-+-+-+
		Chunk basic header 1

		0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|fmt| 0			| cs id - 64	|
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		Chunk basic header 2


		0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|fmt| 1			| cs id - 64					|
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		Chunk basic header 3
	*/
	  
	/* 根据上面协议文档中的说明,对header进行拼接 */
	if (pkt->channel_id > 65599)
	{
		printf("[RTMP_Send_packet] pkt channel id error, channel id %d\n", pkt->channel_id);
	}

	if (pkt->channel_id < 64)
	{
		*p = (pkt->fmt_type << 6) | (pkt->channel_id);
		p++;
	}
	else if (pkt->channel_id >= 64 && pkt->channel_id < 320)
	{
		*p = (pkt->fmt_type << 6) | 0;
		p++;

		*p = pkt->channel_id - 64;
		p++;
	}
	else
	{
		*p = (pkt->fmt_type << 6) | 1;
		p++;
		*p = pkt->channel_id - 64;
		p++;
	}

	/*
		根据协议文档,当fmt_type为0时,
		timestamp为3个byte, msg_length 为3个byte,
		message type id 为1个byte,msg stream id 为4个byte
	*/
	if (pkt->fmt_type == 0)
	{
		//set timestamp
		RTMP_write3byte_to_buffer(&p, pkt->time_stamp);

		//set msg_length
		RTMP_write3byte_to_buffer(&p, pkt->data_size);

		//set msg_type
		RTMP_write1byte_to_buffer(&p, pkt->msg_type);

		//set msg stream id
		RTMP_write4byte_to_buffer_l(&p, pkt->msg_stream_id);	//小端序	
	}


	//msg header end
	int send_ret = -1;
	send_ret = RTMP_Write((char*)pkt_header, p - pkt_header);

	if (send_ret <= 0)
	{
		printf("[RTMP_Send_packet] fmt type 0, send data error %d\n", WSAGetLastError());
		return -1;
	}

	int send_size = 0; 
	while (send_size < pkt->data_size)
	{
		int towrite = RTMP_MIN(g_context.in_chunk_size, pkt->data_size - send_size);
		send_ret = RTMP_Write((char*)pkt->data + send_size, towrite);
		if (send_ret <= 0)
		{
			printf("[RTMP_Send_packet] fmt type 0, send data error %d\n", WSAGetLastError());
			return -1;
		}
		send_size += send_ret;

		//write header
		if (send_size < pkt->data_size)
		{
			uint8_t marker = 0xC0 | pkt->channel_id;
			send_ret = RTMP_Write((char*)&marker, sizeof(marker));
			if (send_ret <= 0)
			{
				printf("[RTMP_Send_packet] fmt type 0, send header error %d\n", WSAGetLastError());
				return -1;
			}
		}
			
	}


	return 0;
}
Пример #14
0
//Publish using RTMP_Write()  
int publish_using_write(){  
	uint32_t start_time=0;  
	uint32_t now_time=0;  
	uint32_t pre_frame_time=0;  
	uint32_t lasttime=0;  
	int bNextIsKey=0;  
	char* pFileBuf=NULL;  

	//read from tag header  
	uint32_t type=0;  
	uint32_t datalength=0;  
	uint32_t timestamp=0;  

	RTMP *rtmp=NULL;                             

	FILE*fp=NULL;  
	fp=fopen("cuc_ieschool.flv","rb");  
	if (!fp){  
		RTMP_LogPrintf("Open File Error.\n");  
//		CleanupSockets();  
		return -1;  
	}  

	/* set log level */  
	//RTMP_LogLevel loglvl=RTMP_LOGDEBUG;  
	//RTMP_LogSetLevel(loglvl);  

//	if (!InitSockets()){  
//		RTMP_LogPrintf("Init Socket Err\n");  
//		return -1;  
//	}  

	rtmp=RTMP_Alloc();  
	RTMP_Init(rtmp);  
	//set connection timeout,default 30s  
	rtmp->Link.timeout=5;                        
	if(!RTMP_SetupURL(rtmp,"rtmp://localhost/publishlive/livestream"))  
	{  
		RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n");  
		RTMP_Free(rtmp);  
	//	CleanupSockets();  
		return -1;  
	}  

	RTMP_EnableWrite(rtmp);  
	//1hour  
	RTMP_SetBufferMS(rtmp, 3600*1000);           
	if (!RTMP_Connect(rtmp,NULL)){  
		RTMP_Log(RTMP_LOGERROR,"Connect Err\n");  
		RTMP_Free(rtmp);  
//		CleanupSockets();  
		return -1;  
	}  

	if (!RTMP_ConnectStream(rtmp,0)){  
		RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n");  
		RTMP_Close(rtmp);  
		RTMP_Free(rtmp);  
		//CleanupSockets();  
		return -1;  
	}  

	printf("Start to send data ...\n");  

	//jump over FLV Header  
	fseek(fp,9,SEEK_SET);       
	//jump over previousTagSizen  
	fseek(fp,4,SEEK_CUR);     
	start_time=RTMP_GetTime();  
	while(1)  
	{  
		if((((now_time=RTMP_GetTime())-start_time)  
					<(pre_frame_time)) && bNextIsKey){          
			//wait for 1 sec if the send process is too fast  
			//this mechanism is not very good,need some improvement  
			if(pre_frame_time>lasttime){  
				RTMP_LogPrintf("TimeStamp:%8lu ms\n", pre_frame_time);  
				lasttime=pre_frame_time;  
			}  
			sleep(1);  
			continue;  
		}  

		//jump over type  
		fseek(fp,1,SEEK_CUR);     
		if(!ReadU24(&datalength,fp))  
			break;  
		if(!ReadTime(&timestamp,fp))  
			break;  
		//jump back  
		fseek(fp,-8,SEEK_CUR);    

		pFileBuf=(char*)malloc(11+datalength+4);  
		memset(pFileBuf,0,11+datalength+4);  
		if(fread(pFileBuf,1,11+datalength+4,fp)!=(11+datalength+4))  
			break;  

		pre_frame_time=timestamp;  

		if (!RTMP_IsConnected(rtmp)){  
			RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n");  
			break;  
		}  
		if (!RTMP_Write(rtmp,pFileBuf,11+datalength+4)){  
			RTMP_Log(RTMP_LOGERROR,"Rtmp Write Error\n");  
			break;  
		}  

		free(pFileBuf);  
		pFileBuf=NULL;  

		if(!PeekU8(&type,fp))  
			break;  
		if(type==0x09){  
			if(fseek(fp,11,SEEK_CUR)!=0)  
				break;  
			if(!PeekU8(&type,fp)){  
				break;  
			}  
			if(type==0x17)  
				bNextIsKey=1;  
			else  
				bNextIsKey=0;  
			fseek(fp,-11,SEEK_CUR);  
		}  
	}  

	RTMP_LogPrintf("\nSend Data Over\n");  

	if(fp)  
		fclose(fp);  

	if (rtmp!=NULL){  
		RTMP_Close(rtmp);          
		RTMP_Free(rtmp);  
		rtmp=NULL;  
	}  

	if(pFileBuf){  
		free(pFileBuf);  
		pFileBuf=NULL;  
	}  

	//CleanupSockets();  
	return 0;  
}  
Пример #15
0
static GstFlowReturn
gst_rtmp_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstRTMPSink *sink = GST_RTMP_SINK (bsink);
  GstBuffer *reffed_buf = NULL;
  GstMapInfo map;

  if (sink->first) {
    /* open the connection */
    if (!RTMP_IsConnected (sink->rtmp)) {
      if (!RTMP_Connect (sink->rtmp, NULL)
          || !RTMP_ConnectStream (sink->rtmp, 0)) {
        GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
            ("Could not connect to RTMP stream \"%s\" for writing", sink->uri));
        RTMP_Free (sink->rtmp);
        sink->rtmp = NULL;
        g_free (sink->rtmp_uri);
        sink->rtmp_uri = NULL;
        return GST_FLOW_ERROR;
      }
      GST_DEBUG_OBJECT (sink, "Opened connection to %s", sink->rtmp_uri);
    }

    /* FIXME: Parse the first buffer and see if it contains a header plus a packet instead
     * of just assuming it's only the header */
    GST_LOG_OBJECT (sink, "Caching first buffer of size %" G_GSIZE_FORMAT
        " for concatenation", gst_buffer_get_size (buf));
    gst_buffer_replace (&sink->cache, buf);
    sink->first = FALSE;
    return GST_FLOW_OK;
  }

  if (sink->cache) {
    GST_LOG_OBJECT (sink, "Joining 2nd buffer of size %" G_GSIZE_FORMAT
        " to cached buf", gst_buffer_get_size (buf));
    gst_buffer_ref (buf);
    reffed_buf = buf = gst_buffer_append (sink->cache, buf);
    sink->cache = NULL;
  }

  GST_LOG_OBJECT (sink, "Sending %" G_GSIZE_FORMAT " bytes to RTMP server",
      gst_buffer_get_size (buf));

  gst_buffer_map (buf, &map, GST_MAP_READ);

  if (RTMP_Write (sink->rtmp, (char *) map.data, map.size) <= 0)
    goto write_failed;

  gst_buffer_unmap (buf, &map);
  if (reffed_buf)
    gst_buffer_unref (reffed_buf);

  return GST_FLOW_OK;

  /* ERRORS */
write_failed:
  {
    GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), ("Failed to write data"));
    gst_buffer_unmap (buf, &map);
    if (reffed_buf)
      gst_buffer_unref (reffed_buf);
    return GST_FLOW_ERROR;
  }
}
/*
 * Class:     net_butterflytv_rtmp_client_RtmpClient
 * Method:    write
 * Signature: ([CI)I
 */
JNIEXPORT jint JNICALL Java_net_ossrs_sea_RtmpClient_write
        (JNIEnv * env, jobject thiz, jcharArray data, jint size) {

    return RTMP_Write(rtmp, data, size);
}
Пример #17
0
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
{
    RTMP *r = s->priv_data;

    return RTMP_Write(r, buf, size);
}
Пример #18
0
int rtmp_write(LibRTMPContext *ctx , const char *buf, int size)
{
    RTMP *r = &ctx->rtmp;
    return RTMP_Write(r, buf, size);
}