Exemple #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);
        }
    }
}
Exemple #2
0
void RtmpAudio::process_recv_queue(unsigned int ref_ts)
{
  int size;

  // flush the recv queue into the playout buffer
  m_q_recv.lock();
  while(!q_recv.empty()){

    RTMPPacket p = q_recv.front();
    q_recv.pop();
    m_q_recv.unlock();

    //TODO:
    // - copy RTMP payload into this->samples
    // - decode
    // - put packet in playout buffer

    if(p.m_nBodySize <= (unsigned int)AUDIO_BUFFER_SIZE){
      

      size = p.m_nBodySize-1;
      memcpy((unsigned char*)samples, p.m_body+1, size);

      size = decode(size);
      if(size <= 0){
	ERROR("decode() returned %i\n",size);
	return;
      }
      
      // TODO: generate some reasonable RTP timestamp
      //
      bool begin_talk = false;
      if(!recv_offset_i){
	recv_rtp_offset  = ref_ts;
	recv_rtmp_offset = p.m_nTimeStamp;
	recv_offset_i = true;
	begin_talk = true;
      }

      unsigned int rtp_ts = (p.m_nTimeStamp - recv_rtmp_offset) * (SPEEX_WB_SAMPLE_RATE/1000);

      playout_buffer.write(ref_ts, rtp_ts, (ShortSample*)((unsigned char *)samples),
			   PCM16_B2S(size), begin_talk);
      
      RTMPPacket_Free(&p);    
    }

    m_q_recv.lock();
  }
  m_q_recv.unlock();
}
void  RtmpSessionFini(RTMP_SESSION *pSession)
{
	if(NULL != pSession->prtmp)
	{
		RTMP_Free(pSession->prtmp);
		pSession->prtmp = NULL;
	}

	if(NULL != pSession->pPkt)
	{
		RTMPPacket_Free(pSession->pPkt);
		free(pSession->pPkt);
		pSession->pPkt = NULL;
	}
	
	return ;	
}
void LibRtmp::SendSetChunkSize(unsigned int chunkSize)
{
    RTMPPacket rtmp_pakt;
    RTMPPacket_Reset(&rtmp_pakt);
    RTMPPacket_Alloc(&rtmp_pakt, 4);

    rtmp_pakt.m_packetType = 0x01;
    rtmp_pakt.m_nChannel = 0x02;    // control channel
    rtmp_pakt.m_headerType = RTMP_PACKET_SIZE_LARGE;
    rtmp_pakt.m_nInfoField2 = 0;


    rtmp_pakt.m_nBodySize = 4;
    UI32ToBytes(rtmp_pakt.m_body, chunkSize);

    RTMP_SendPacket(rtmp_, &rtmp_pakt, 0);
    RTMPPacket_Free(&rtmp_pakt);
}
bool LibRtmp::Send(const char* buf, int bufLen, int type, unsigned int timestamp)
{
    RTMPPacket rtmp_pakt;
    RTMPPacket_Reset(&rtmp_pakt);
    RTMPPacket_Alloc(&rtmp_pakt, bufLen);

    rtmp_pakt.m_packetType = type;
    rtmp_pakt.m_nBodySize = bufLen;
    rtmp_pakt.m_nTimeStamp = timestamp;
    rtmp_pakt.m_nChannel = 4;
    rtmp_pakt.m_headerType = RTMP_PACKET_SIZE_LARGE;
    rtmp_pakt.m_nInfoField2 = rtmp_->m_stream_id;
    memcpy(rtmp_pakt.m_body, buf, bufLen);

    int retval = RTMP_SendPacket(rtmp_, &rtmp_pakt, 0);
    RTMPPacket_Free(&rtmp_pakt);

    return !!retval;
}
int RtmpSessionHandshake(RTMP_SESSION *pSession)
{
	int iRet = 0;
	RTMPPacket *packet = (RTMPPacket *)malloc(sizeof(RTMPPacket));
	if(NULL == packet)
	{
		
		return ERROR_FAILED;
	}
	RTMPPacket_Init(packet);
	pSession->pPkt = packet;
	
	RTMP *rtmp = RTMP_Alloc(); 
	if(NULL == rtmp )
	{
		return ERROR_FAILED;
	}

	RTMP_Init(rtmp);
	rtmp->m_sb.sb_socket =  pSession->socket;
	pSession->prtmp = rtmp;

	pSession->state = RTMPSERVER_STATE_INIT;
	
	/* 进行握手处理 */
	if(RTMP_Serve(rtmp))
	{
		RTMPPacket_Free(pSession->pPkt);
		RTMPPacket_Init(pSession->pPkt);
		pSession->handshake = 1;
		pSession->arglen = 0;
		SetNonBlocking(pSession->socket);
	}
	else
	{
		iRet = -1;
	}
	
	return iRet;
}
Exemple #7
0
static event_t *
rtmp_loop(rtmp_t *r, media_pipe_t *mp, char *url, char *errbuf, size_t errlen)
{
  RTMPPacket p = {0};
  int pos = -1, ret;
  uint32_t dts;
  event_t *e = NULL;

  while(1) {


    if(pos == -1) {

      mp->mp_eof = 0;
      ret = RTMP_GetNextMediaPacket(r->r, &p);

      if(ret == 2) {
	/* Wait for queues to drain */
	mp->mp_eof = 1;
      again:
	e = mp_wait_for_empty_queues(mp);

	if(e != NULL) {
	  e = rtmp_process_event(r, e, NULL);
	  if(e == NULL)
	    goto again;
	}

	if(e == NULL)
	  e = event_create_type(EVENT_EOF);
	break;
      }

      if(ret == 0) {
	int64_t restartpos = r->seekpos_video;

        if(cancellable_is_cancelled(mp->mp_cancellable)) {
          snprintf(errbuf, errlen, "Cancelled");
          return NULL;
        }

	TRACE(TRACE_ERROR, "RTMP", "Disconnected");
	sleep(1);

	if(restartpos == AV_NOPTS_VALUE) {
	  snprintf(errbuf, errlen,
		   "Giving up restart since nothing was decoded");
	  return NULL;
	}


	RTMP_Close(r->r);

	RTMP_Init(r->r, mp->mp_cancellable);

	memset(&p, 0, sizeof(p));

	TRACE(TRACE_DEBUG, "RTMP", "Reconnecting stream at pos %ld", 
	      restartpos);

	if(!RTMP_SetupURL(r->r, url)) {
	  snprintf(errbuf, errlen, "Unable to setup RTMP session");
	  return NULL;
	}

	if(!RTMP_Connect(r->r, NULL, errbuf, errlen, 5000)) {
	  return NULL;
	}

	if(!RTMP_ConnectStream(r->r, 0)) {
	  snprintf(errbuf, errlen, "Unable to stream RTMP session");
	  return NULL;
	}

	if(mp->mp_flags & MP_CAN_SEEK)
	  RTMP_SendSeek(r->r, restartpos / 1000);
	continue;
      }

      dts = p.m_nTimeStamp;

      switch(p.m_packetType) {
      case RTMP_PACKET_TYPE_INFO:
	if(handle_metadata(r, p.m_body, p.m_nBodySize, mp, errbuf, errlen)) {
	  RTMPPacket_Free(&p);
	  return NULL;
	}
	break;

      case RTMP_PACKET_TYPE_VIDEO:
	e = get_packet_v(r, (void *)p.m_body, p.m_nBodySize, dts, mp);
	break;

      case RTMP_PACKET_TYPE_AUDIO:
	e = get_packet_a(r, (void *)p.m_body, p.m_nBodySize, dts, mp);
	break;
	
      case 0x16:
	pos = 0;
	break;
      default:
	TRACE(TRACE_DEBUG, "RTMP", 
	      "Got unknown packet type %d\n", p.m_packetType);
	break;
      }
      if(pos == -1)
	RTMPPacket_Free(&p);
    }

    if(pos != -1) {
      if(pos + 11 < p.m_nBodySize) {
	uint32_t ds = AMF_DecodeInt24(p.m_body + pos + 1);
	  
	if(pos + 11 + ds + 4 > p.m_nBodySize) {
	  snprintf(errbuf, errlen, "Corrupt stream");
	  RTMPPacket_Free(&p);
	  return NULL;
	}

	dts = AMF_DecodeInt24(p.m_body + pos + 4);
	dts |= (p.m_body[pos + 7] << 24);

	if(p.m_body[pos] == RTMP_PACKET_TYPE_INFO) {
	  if(handle_metadata(r, p.m_body, p.m_nBodySize, mp, errbuf, errlen)) {
	    RTMPPacket_Free(&p);
	    return NULL;
	  }
	} else if(p.m_body[pos] == RTMP_PACKET_TYPE_VIDEO) {
	  e = get_packet_v(r, (void *)p.m_body + pos + 11, ds, dts, mp);
	} else if(p.m_body[pos] == RTMP_PACKET_TYPE_AUDIO) {
	  e = get_packet_a(r, (void *)p.m_body + pos + 11, ds, dts, mp);
	} else {
	  TRACE(TRACE_DEBUG, "RTMP", 
		"Got unknown packet type %d\n", p.m_body[pos]);
	}
	pos += 11 + ds + 4;
      } else {
	pos = -1;
	RTMPPacket_Free(&p);
      }
    }
    if(e != NULL)
      break;
  }
  return e;
}
Exemple #8
0
void doServe(STREAMING_SERVER * server,	// server socket and state (our listening socket)
  int sockfd	// client connection socket
  )
{
  server->state = STREAMING_IN_PROGRESS;

  RTMP rtmp = { 0 };		/* our session with the real client */
  RTMPPacket packet = { 0 };

  // timeout for http requests
  fd_set fds;
  struct timeval tv;

  memset(&tv, 0, sizeof(struct timeval));
  tv.tv_sec = 5;

  FD_ZERO(&fds);
  FD_SET(sockfd, &fds);

  if (select(sockfd + 1, &fds, NULL, NULL, &tv) <= 0)
    {
      RTMP_Log(RTMP_LOGERROR, "Request timeout/select failed, ignoring request");
      goto quit;
    }
  else
    {
      RTMP_Init(&rtmp);
      rtmp.m_sb.sb_socket = sockfd;
      if (!RTMP_Serve(&rtmp))
	{
	  RTMP_Log(RTMP_LOGERROR, "Handshake failed");
	  goto cleanup;
	}
    }
  server->arglen = 0;
  while (RTMP_IsConnected(&rtmp) && RTMP_ReadPacket(&rtmp, &packet))
    {
      if (!RTMPPacket_IsReady(&packet))
	continue;
      ServePacket(server, &rtmp, &packet);
      RTMPPacket_Free(&packet);
    }

cleanup:
  RTMP_LogPrintf("Closing connection... ");
  RTMP_Close(&rtmp);
  /* Should probably be done by RTMP_Close() ... */
  rtmp.Link.playpath.av_val = NULL;
  rtmp.Link.tcUrl.av_val = NULL;
  rtmp.Link.swfUrl.av_val = NULL;
  rtmp.Link.pageUrl.av_val = NULL;
  rtmp.Link.app.av_val = NULL;
  rtmp.Link.flashVer.av_val = NULL;
  RTMP_LogPrintf("done!\n\n");

quit:
  if (server->state == STREAMING_IN_PROGRESS)
    server->state = STREAMING_ACCEPTING;

  return;
}
Exemple #9
0
// Returns 0 for OK/Failed/error, 1 for 'Stop or Complete'
int
ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int offset)
{
  const char *body;
  unsigned int nBodySize;
  int ret = 0, nRes;

  body = packet->m_body + offset;
  nBodySize = packet->m_nBodySize - offset;

  if (body[0] != 0x02)		// make sure it is a string method name we start with
    {
      RTMP_Log(RTMP_LOGWARNING, "%s, Sanity failed. no string method in invoke packet",
	  __FUNCTION__);
      return 0;
    }

  AMFObject obj;
  nRes = AMF_Decode(&obj, body, nBodySize, FALSE);
  if (nRes < 0)
    {
      RTMP_Log(RTMP_LOGERROR, "%s, error decoding invoke packet", __FUNCTION__);
      return 0;
    }

  AMF_Dump(&obj);
  AVal method;
  AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &method);
  double txn = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 1));
  RTMP_Log(RTMP_LOGDEBUG, "%s, client invoking <%s>", __FUNCTION__, method.av_val);

  if (AVMATCH(&method, &av_connect))
    {
      AMFObject cobj;
      AVal pname, pval;
      int i;

      server->connect = packet->m_body;
      packet->m_body = NULL;

      AMFProp_GetObject(AMF_GetProp(&obj, NULL, 2), &cobj);
      for (i=0; i<cobj.o_num; i++)
	{
	  pname = cobj.o_props[i].p_name;
	  pval.av_val = NULL;
	  pval.av_len = 0;
	  if (cobj.o_props[i].p_type == AMF_STRING)
	    pval = cobj.o_props[i].p_vu.p_aval;
	  if (AVMATCH(&pname, &av_app))
	    {
	      r->Link.app = pval;
	      pval.av_val = NULL;
	      if (!r->Link.app.av_val)
	        r->Link.app.av_val = "";
	      server->arglen += 6 + pval.av_len;
	      server->argc += 2;
	    }
	  else if (AVMATCH(&pname, &av_flashVer))
	    {
	      r->Link.flashVer = pval;
	      pval.av_val = NULL;
	      server->arglen += 6 + pval.av_len;
	      server->argc += 2;
	    }
	  else if (AVMATCH(&pname, &av_swfUrl))
	    {
	      r->Link.swfUrl = pval;
	      pval.av_val = NULL;
	      server->arglen += 6 + pval.av_len;
	      server->argc += 2;
	    }
	  else if (AVMATCH(&pname, &av_tcUrl))
	    {
	      r->Link.tcUrl = pval;
	      pval.av_val = NULL;
	      server->arglen += 6 + pval.av_len;
	      server->argc += 2;
	    }
	  else if (AVMATCH(&pname, &av_pageUrl))
	    {
	      r->Link.pageUrl = pval;
	      pval.av_val = NULL;
	      server->arglen += 6 + pval.av_len;
	      server->argc += 2;
	    }
	  else if (AVMATCH(&pname, &av_audioCodecs))
	    {
	      r->m_fAudioCodecs = cobj.o_props[i].p_vu.p_number;
	    }
	  else if (AVMATCH(&pname, &av_videoCodecs))
	    {
	      r->m_fVideoCodecs = cobj.o_props[i].p_vu.p_number;
	    }
	  else if (AVMATCH(&pname, &av_objectEncoding))
	    {
	      r->m_fEncoding = cobj.o_props[i].p_vu.p_number;
	    }
	}
      /* Still have more parameters? Copy them */
      if (obj.o_num > 3)
	{
	  int i = obj.o_num - 3;
	  r->Link.extras.o_num = i;
	  r->Link.extras.o_props = malloc(i*sizeof(AMFObjectProperty));
	  memcpy(r->Link.extras.o_props, obj.o_props+3, i*sizeof(AMFObjectProperty));
	  obj.o_num = 3;
	  server->arglen += countAMF(&r->Link.extras, &server->argc);
	}
      SendConnectResult(r, txn);
    }
  else if (AVMATCH(&method, &av_createStream))
    {
      SendResultNumber(r, txn, ++server->streamID);
    }
  else if (AVMATCH(&method, &av_getStreamLength))
    {
      SendResultNumber(r, txn, 10.0);
    }
  else if (AVMATCH(&method, &av_play))
    {
      char *file, *p, *q, *cmd, *ptr;
      AVal *argv, av;
      int len, argc;
      uint32_t now;
      RTMPPacket pc = {0};
      AMFProp_GetString(AMF_GetProp(&obj, NULL, 3), &r->Link.playpath);
      /*
      r->Link.seekTime = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 4));
      if (obj.o_num > 5)
	r->Link.length = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 5));
      */
      if (r->Link.tcUrl.av_len)
	{
	  len = server->arglen + r->Link.playpath.av_len + 4 +
	    sizeof("rtmpdump") + r->Link.playpath.av_len + 12;
	  server->argc += 5;

	  cmd = malloc(len + server->argc * sizeof(AVal));
	  ptr = cmd;
	  argv = (AVal *)(cmd + len);
	  argv[0].av_val = cmd;
	  argv[0].av_len = sizeof("rtmpdump")-1;
	  ptr += sprintf(ptr, "rtmpdump");
	  argc = 1;

	  argv[argc].av_val = ptr + 1;
	  argv[argc++].av_len = 2;
	  argv[argc].av_val = ptr + 5;
	  ptr += sprintf(ptr," -r \"%s\"", r->Link.tcUrl.av_val);
	  argv[argc++].av_len = r->Link.tcUrl.av_len;

	  if (r->Link.app.av_val)
	    {
	      argv[argc].av_val = ptr + 1;
	      argv[argc++].av_len = 2;
	      argv[argc].av_val = ptr + 5;
	      ptr += sprintf(ptr, " -a \"%s\"", r->Link.app.av_val);
	      argv[argc++].av_len = r->Link.app.av_len;
	    }
	  if (r->Link.flashVer.av_val)
	    {
	      argv[argc].av_val = ptr + 1;
	      argv[argc++].av_len = 2;
	      argv[argc].av_val = ptr + 5;
	      ptr += sprintf(ptr, " -f \"%s\"", r->Link.flashVer.av_val);
	      argv[argc++].av_len = r->Link.flashVer.av_len;
	    }
	  if (r->Link.swfUrl.av_val)
	    {
	      argv[argc].av_val = ptr + 1;
	      argv[argc++].av_len = 2;
	      argv[argc].av_val = ptr + 5;
	      ptr += sprintf(ptr, " -W \"%s\"", r->Link.swfUrl.av_val);
	      argv[argc++].av_len = r->Link.swfUrl.av_len;
	    }
	  if (r->Link.pageUrl.av_val)
	    {
	      argv[argc].av_val = ptr + 1;
	      argv[argc++].av_len = 2;
	      argv[argc].av_val = ptr + 5;
	      ptr += sprintf(ptr, " -p \"%s\"", r->Link.pageUrl.av_val);
	      argv[argc++].av_len = r->Link.pageUrl.av_len;
	    }
	  if (r->Link.extras.o_num) {
	    ptr = dumpAMF(&r->Link.extras, ptr, argv, &argc);
	    AMF_Reset(&r->Link.extras);
	  }
	  argv[argc].av_val = ptr + 1;
	  argv[argc++].av_len = 2;
	  argv[argc].av_val = ptr + 5;
	  ptr += sprintf(ptr, " -y \"%.*s\"",
	    r->Link.playpath.av_len, r->Link.playpath.av_val);
	  argv[argc++].av_len = r->Link.playpath.av_len;

	  av = r->Link.playpath;
	  /* strip trailing URL parameters */
	  q = memchr(av.av_val, '?', av.av_len);
	  if (q)
	    {
	      if (q == av.av_val)
		{
		  av.av_val++;
		  av.av_len--;
		}
	      else
		{
		  av.av_len = q - av.av_val;
		}
	    }
	  /* strip leading slash components */
	  for (p=av.av_val+av.av_len-1; p>=av.av_val; p--)
	    if (*p == '/')
	      {
		p++;
		av.av_len -= p - av.av_val;
		av.av_val = p;
		break;
	      }
	  /* skip leading dot */
	  if (av.av_val[0] == '.')
	    {
	      av.av_val++;
	      av.av_len--;
	    }
	  file = malloc(av.av_len+5);

	  memcpy(file, av.av_val, av.av_len);
	  file[av.av_len] = '\0';
	  for (p=file; *p; p++)
	    if (*p == ':')
	      *p = '_';

	  /* Add extension if none present */
	  if (file[av.av_len - 4] != '.')
	    {
	      av.av_len += 4;
	    }
	  /* Always use flv extension, regardless of original */
	  if (strcmp(file+av.av_len-4, ".flv"))
	    {
	      strcpy(file+av.av_len-4, ".flv");
	    }
	  argv[argc].av_val = ptr + 1;
	  argv[argc++].av_len = 2;
	  argv[argc].av_val = file;
	  argv[argc].av_len = av.av_len;
	  ptr += sprintf(ptr, " -o %s", file);
	  now = RTMP_GetTime();
	  if (now - server->filetime < DUPTIME && AVMATCH(&argv[argc], &server->filename))
	    {
	      printf("Duplicate request, skipping.\n");
	      free(file);
	    }
	  else
	    {
	      printf("\n%s\n\n", cmd);
	      fflush(stdout);
	      server->filetime = now;
	      free(server->filename.av_val);
	      server->filename = argv[argc++];
	      spawn_dumper(argc, argv, cmd);
	    }

	  free(cmd);
	}
      pc.m_body = server->connect;
      server->connect = NULL;
      RTMPPacket_Free(&pc);
      ret = 1;
	  RTMP_SendCtrl(r, 0, 1, 0);
	  SendPlayStart(r);
	  RTMP_SendCtrl(r, 1, 1, 0);
	  SendPlayStop(r);
    }
  AMF_Reset(&obj);
  return ret;
}
Exemple #10
0
int RtmpAudio::send(unsigned int user_ts, unsigned int size)
{
  m_sender.lock();

  if(!sender || !play_stream_id) {
    //DBG("!sender || !play_stream_id");
    m_sender.unlock();
    return 0;
  }

  // - generate a new RTMP audio packet
  // - send packet

  RTMPPacket packet;
  RTMPPacket_Reset(&packet);

  packet.m_headerType  = send_offset_i ? 
    RTMP_PACKET_SIZE_MEDIUM 
    : RTMP_PACKET_SIZE_LARGE;

  packet.m_packetType  = RTMP_PACKET_TYPE_AUDIO;
  packet.m_nChannel    = 4;//TODO
  packet.m_nInfoField2 = play_stream_id;

  if(!send_offset_i){
    send_rtmp_offset = user_ts;
    send_offset_i = true;
  }
  
  unsigned int rtmp_ts = (user_ts - send_rtmp_offset) 
    / (SPEEX_WB_SAMPLE_RATE/1000);
  packet.m_nTimeStamp  = rtmp_ts;

  RTMPPacket_Alloc(&packet,size+1);
  packet.m_nBodySize = size+1;

// soundType 	(byte & 0x01) » 0 	
//   0: mono, 1: stereo
// soundSize 	(byte & 0x02) » 1 	
//   0: 8-bit, 1: 16-bit
// soundRate 	(byte & 0x0C) » 2 	
//   0: 5.5 kHz, 1: 11 kHz, 2: 22 kHz, 3: 44 kHz
// soundFormat 	(byte & 0xf0) » 4 	
//   0: Uncompressed, 1: ADPCM, 2: MP3, 5: Nellymoser 8kHz mono, 6: Nellymoser, 11: Speex 


  // 0xB2: speex, 16kHz
  packet.m_body[0] = 0xB2;
  memcpy(packet.m_body+1,(unsigned char*)samples,size);

  //DBG("sending audio packet: size=%u rtmp_ts=%u StreamID=%u (rtp_ts=%u)\n",
  //    size+1,rtmp_ts,play_stream_id,user_ts);

  sender->push_back(packet);
  m_sender.unlock();

  //dump_audio(&packet);
  RTMPPacket_Free(&packet);

  return size;
}
Exemple #11
0
//Publish using RTMP_SendPacket()  
int publish_using_packet(){  
	RTMP *rtmp=NULL;                             
	RTMPPacket *packet=NULL;  
	uint32_t start_time=0;  
	uint32_t now_time=0;  
	//the timestamp of the previous frame  
	long pre_frame_time=0;  
	long lasttime=0;  
	int bNextIsKey=1;  
	uint32_t preTagsize=0;  

	//packet attributes  
	uint32_t type=0;                          
	uint32_t datalength=0;             
	uint32_t timestamp=0;             
	uint32_t streamid=0;                          

	FILE*fp=NULL;  
	fp=fopen("../live.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://101.251.251.93:1935/myapp/mystream"))  
	{  
		RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n");  
		RTMP_Free(rtmp);  
	//	CleanupSockets();  
		return -1;  
	}  

	//if unable,the AMF command would be 'play' instead of 'publish'  
	RTMP_EnableWrite(rtmp);       

	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;  
	}  

	packet=(RTMPPacket*)malloc(sizeof(RTMPPacket));  
	RTMPPacket_Alloc(packet,1024*64);  
	RTMPPacket_Reset(packet);  

	packet->m_hasAbsTimestamp = 0;          
	packet->m_nChannel = 0x04;  
	packet->m_nInfoField2 = rtmp->m_stream_id;  

	RTMP_LogPrintf("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;  
		}  

		//not quite the same as FLV spec  
		if(!ReadU8(&type,fp))       
			break;  
		if(!ReadU24(&datalength,fp))  
			break;  
		if(!ReadTime(&timestamp,fp))  
			break;  
		if(!ReadU24(&streamid,fp))  
			break;  

		if (type!=0x08&&type!=0x09){  
			//jump over non_audio and non_video frame,  
			//jump over next previousTagSizen at the same time  
			fseek(fp,datalength+4,SEEK_CUR);  
			continue;  
		}  

		if(fread(packet->m_body,1,datalength,fp)!=datalength)  
			break;  

		packet->m_headerType = RTMP_PACKET_SIZE_LARGE;  
		packet->m_nTimeStamp = timestamp;  
		packet->m_packetType = type;  
		packet->m_nBodySize  = datalength;  
		pre_frame_time=timestamp;  

		if (!RTMP_IsConnected(rtmp)){  
			RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n");  
			break;  
		}  
		if (!RTMP_SendPacket(rtmp,packet,0)){  
			RTMP_Log(RTMP_LOGERROR,"Send Error\n");  
			break;  
		}  

		if(!ReadU32(&preTagsize,fp))  
			break;  

		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 (packet!=NULL){  
		RTMPPacket_Free(packet);      
		free(packet);  
		packet=NULL;  
	}  

//	CleanupSockets();  
	return 0;  
}  
Exemple #12
0
static event_t *
rtmp_loop(rtmp_t *r, media_pipe_t *mp, char *url, char *errbuf, size_t errlen)
{
  RTMPPacket p = {0};
  int pos = -1, ret;
  uint32_t dts;
  event_t *e = NULL;

  mp_set_playstatus_by_hold(mp, 0, NULL);

  while(1) {


    if(pos == -1) {

      mp->mp_eof = 0;
      ret = RTMP_GetNextMediaPacket(r->r, &p);

      if(ret == 2) {
	/* Wait for queues to drain */
	mp->mp_eof = 1;
      again:
	e = mp_wait_for_empty_queues(mp);

	if(e != NULL) {
	  e = rtmp_process_event(r, e, NULL);
	  if(e == NULL)
	    goto again;
	}
	mp_set_playstatus_stop(mp);

	if(e == NULL)
	  e = event_create_type(EVENT_EOF);
	break;
      }

      if(ret == 0) {
	RTMP_Close(r->r);
	  
	RTMP_Init(r->r);

	memset(&p, 0, sizeof(p));

	TRACE(TRACE_DEBUG, "RTMP", "Reconnecting stream at pos %d", 
	      r->seekbase);

	if(!RTMP_SetupURL(r->r, url)) {
	  snprintf(errbuf, errlen, "Unable to setup RTMP session");
	  e = NULL;
	  break;
	}

	if(!RTMP_Connect(r->r, NULL)) {
	  snprintf(errbuf, errlen, "Unable to connect RTMP session");
	  e = NULL;
	  break;
	}

	if(!RTMP_ConnectStream(r->r, r->can_seek ? r->seekbase / 1000 : 0)) {
	  snprintf(errbuf, errlen, "Unable to stream RTMP session");
	  return NULL;
	}
	r->epoch++;


	r->lastdts = 0;
	r->seekbase = AV_NOPTS_VALUE;
	mp_flush(mp, 0);
	continue;
      }

      dts = p.m_nTimeStamp;

      switch(p.m_packetType) {
      case RTMP_PACKET_TYPE_INFO:
	if(handle_metadata(r, p.m_body, p.m_nBodySize, mp, errbuf, errlen)) {
	  RTMPPacket_Free(&p);
	  return NULL;
	}
	break;

      case RTMP_PACKET_TYPE_VIDEO:
	e = get_packet_v(r, (void *)p.m_body, p.m_nBodySize, dts, mp);
	break;

      case RTMP_PACKET_TYPE_AUDIO:
	e = get_packet_a(r, (void *)p.m_body, p.m_nBodySize, dts, mp);
	break;
	
      case 0x16:
	pos = 0;
	break;
      default:
	TRACE(TRACE_DEBUG, "RTMP", 
	      "Got unknown packet type %d\n", p.m_packetType);
	break;
      }
      if(pos == -1)
	RTMPPacket_Free(&p);
    }

    if(pos != -1) {
      if(pos + 11 < p.m_nBodySize) {
	uint32_t ds = AMF_DecodeInt24(p.m_body + pos + 1);
	  
	if(pos + 11 + ds + 4 > p.m_nBodySize) {
	  snprintf(errbuf, errlen, "Corrupt stream");
	  RTMPPacket_Free(&p);
	  return NULL;
	}

	dts = AMF_DecodeInt24(p.m_body + pos + 4);
	dts |= (p.m_body[pos + 7] << 24);

	if(p.m_body[pos] == RTMP_PACKET_TYPE_INFO) {
	  if(handle_metadata(r, p.m_body, p.m_nBodySize, mp, errbuf, errlen)) {
	    RTMPPacket_Free(&p);
	    return NULL;
	  }
	} else if(p.m_body[pos] == RTMP_PACKET_TYPE_VIDEO) {
	  e = get_packet_v(r, (void *)p.m_body + pos + 11, ds, dts, mp);
	} else if(p.m_body[pos] == RTMP_PACKET_TYPE_AUDIO) {
	  e = get_packet_a(r, (void *)p.m_body + pos + 11, ds, dts, mp);
	} else {
	  TRACE(TRACE_DEBUG, "RTMP", 
		"Got unknown packet type %d\n", p.m_body[pos]);
	}
	pos += 11 + ds + 4;
      } else {
	pos = -1;
	RTMPPacket_Free(&p);
      }
    }
    if(e != NULL)
      break;
  }
  return e;
}
static 
void  RtmpDispatchPkt(RTMP_SESSION *pSession, RTMPPacket *pPkt)
{
	RTMP *pRtmp  =  pSession->prtmp;
	/* 处理报文 */	
	RTMP_Log(RTMP_LOGDEBUG, "%s, received packet type %02X, size %u bytes", __FUNCTION__,
pPkt->m_packetType, pPkt->m_nBodySize);
	switch(pPkt->m_packetType)
	{
		case RTMP_PACKET_TYPE_CHUNK_SIZE:
		{
			break;
		}

		case RTMP_PACKET_TYPE_BYTES_READ_REPORT:
		{
			break;
		}

		case RTMP_PACKET_TYPE_CONTROL:
		{
			break;
		}

		case RTMP_PACKET_TYPE_SERVER_BW:
		{
			break;
		}

		case RTMP_PACKET_TYPE_CLIENT_BW:
		{
			break;
		}
		case RTMP_PACKET_TYPE_AUDIO:
		{
			break;
		}

		case RTMP_PACKET_TYPE_VIDEO:
		{
			break;
		}
		case RTMP_PACKET_TYPE_FLEX_STREAM_SEND:
		{
    		break;
    	}

 		case RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT:
 		{
    		break;
		}
  		case RTMP_PACKET_TYPE_FLEX_MESSAGE:
	  	{
		    RTMP_Log(RTMP_LOGDEBUG, "%s, flex message, size %u bytes, not fully supported",
		             __FUNCTION__, pPkt->m_nBodySize);
		    
		    if (SessionInvoke(pSession, pPkt, 1))
		      RTMP_Close(pSession->prtmp);
		    break;
	  	}
  		case RTMP_PACKET_TYPE_INFO:
  		{
    		break;
		}
  		case RTMP_PACKET_TYPE_SHARED_OBJECT:
  		{
    		break;
		}
  		case RTMP_PACKET_TYPE_INVOKE:
  		{
		    RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %u bytes", __FUNCTION__,
		             pPkt->m_nBodySize);
		   
		    if (SessionInvoke(pSession, pPkt, 0))
		      RTMP_Close(pRtmp);
		    break;
		}
  		case RTMP_PACKET_TYPE_FLASH_VIDEO:
  		{
   			break;
   		}
	  	default:
	  	{
	    	RTMP_Log(RTMP_LOGDEBUG, "%s, unknown packet type received: 0x%02x", __FUNCTION__,
	            pPkt->m_packetType);
			#ifdef _DEBUG
			RTMP_LogHex(RTMP_LOGDEBUG, pPkt->m_body, pPkt->m_nBodySize);
			#endif
	  	}
	}

    RTMPPacket_Free(pPkt);
    RTMPPacket_Init(pPkt);
}