예제 #1
0
파일: h264.c 프로젝트: iskey/feng_build
static void frag_fu_a(uint8_t *nal, int fragsize, int mtu,
                      Track *tr)
{
    int start = 1, fraglen;
    uint8_t fu_header, buf[mtu];
    fnc_log(FNC_LOG_VERBOSE, "[h264] frags");
//                p = data + index;
    buf[0] = (nal[0] & 0xe0) | 28; // fu_indicator
    fu_header = nal[0] & 0x1f;
    nal++;
    fragsize--;
    while(fragsize>0) {
        buf[1] = fu_header;
        if (start) {
            start = 0;
            buf[1] = fu_header | (1<<7);
        }
        fraglen = MIN(mtu-2, fragsize);
        if (fraglen == fragsize) {
            buf[1] = fu_header | (1<<6);
        }
        memcpy(buf + 2, nal, fraglen);
        fnc_log(FNC_LOG_VERBOSE, "[h264] Frag %d %d",buf[0], buf[1]);
        mparser_buffer_write(tr,
                             tr->properties.pts,
                             tr->properties.dts,
                             tr->properties.frame_duration,
                             (fragsize<=fraglen),
                             buf, fraglen + 2);
        fragsize -= fraglen;
        nal      += fraglen;
    }
}
예제 #2
0
파일: sock.c 프로젝트: dulton/hm-platform
gint
unix_sock_bind(const gchar *host, gint port, L4_Proto l4)
{
	struct sockaddr_in sin;
	gint sock, err;

	sock = socket(AF_INET, l4 == L4_TCP ? SOCK_STREAM : SOCK_DGRAM, 0);
	if (sock < 0)
	{
		err = -errno;
		fnc_log(FNC_LOG_ERR, "[FC] Create socket failed.");
		return err;
	}

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
	sin.sin_addr.s_addr = host ? inet_addr(host) : INADDR_ANY;

	if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)))
	{
		err = -errno;
		fnc_log(FNC_LOG_ERR, "[FC] Bind socket failed on port '%d'.", port);
		close(sock);
		return err;
	}

	return sock;
}
예제 #3
0
tsocket tcp_connect(unsigned short port, char *addr)
{
	tsocket f;
	int on=1;
	int one = 1;/*used to set SO_KEEPALIVE*/
	
	struct sockaddr_in s;
	int v = 1;
	if ((f = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))<0) {
		fnc_log(FNC_LOG_ERR,"socket() error in tcp_connect.\n" );
		return ERR_GENERIC;
	}
	setsockopt(f, SOL_SOCKET, SO_REUSEADDR, (char *) &v, sizeof(int));
	s.sin_family = AF_INET;
	s.sin_addr.s_addr = inet_addr(addr);//htonl(addr);
	s.sin_port = htons(port);
	// set to non-blocking
	if (ioctl(f, FIONBIO, &on) < 0) {
		fnc_log(FNC_LOG_ERR,"ioctl() error in tcp_connect.\n" );
		return ERR_GENERIC;
	}	
	if (connect(f,(struct sockaddr*)&s, sizeof(s)) < 0) {
		fnc_log(FNC_LOG_ERR,"connect() error in tcp_connect.\n" );
		return ERR_GENERIC;
	}        
	if(setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one))<0){
		fnc_log(FNC_LOG_ERR,"setsockopt() SO_KEEPALIVE error in tcp_connect.\n" );
		return ERR_GENERIC;
	}
	return f;
}
예제 #4
0
static int simple_parse(Track *tr, uint8_t *data, size_t len)
{
    int32_t offset = 0, rem = len;


    if (DEFAULT_MTU >= len) {
        mparser_buffer_write(tr,
                             tr->properties.pts,
                             tr->properties.dts,
                             tr->properties.frame_duration,
                             1,
                             data, len);
        fnc_log(FNC_LOG_VERBOSE, "[simple] no frags");
    } else {
        do {
            offset = len - rem;
            mparser_buffer_write(tr,
                                 tr->properties.pts,
                                 tr->properties.dts,
                                 tr->properties.frame_duration,
                                 (rem <= DEFAULT_MTU),
                                 data + offset, MIN(rem, DEFAULT_MTU));
            rem -= DEFAULT_MTU;
            fnc_log(FNC_LOG_VERBOSE, "[simple] frags");
        } while (rem >= 0);
    }
    fnc_log(FNC_LOG_VERBOSE, "[simple] Frame completed");
    
    
    return ERR_NOERROR;

}
예제 #5
0
int udp_open(unsigned short port,struct sockaddr *s_addr, tsocket *fd)
{
	struct sockaddr_in s;
	int on = 1; //,v=1;

   	if (!*fd) {
		if ((*fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
			fnc_log(FNC_LOG_ERR,"socket() error in udp_open.\n" );
			return ERR_GENERIC;
    		}
		// set to non-blocking
    		if (ioctl(*fd, FIONBIO, &on) < 0) {
			fnc_log(FNC_LOG_ERR,"ioctl() error in udp_open.\n" );
      			return ERR_GENERIC;
    		}
	}

    	s.sin_family = AF_INET;
    	s.sin_addr.s_addr = htonl(INADDR_ANY);
    	s.sin_port =  htons(port);
    	if (bind (*fd, (struct sockaddr *)&s, sizeof (s))) {
		fnc_log(FNC_LOG_ERR,"bind() error in udp_open.\n" );
    		return ERR_GENERIC;
    	}
    	*s_addr=*((struct sockaddr*)&s);

	return ERR_NOERROR;
}
예제 #6
0
파일: main.c 프로젝트: F35X70/feng
/**
 * Drop privileges to the configured user
 *
 * This function takes care of changing the running group and user to
 * those defined in @ref feng_srv::groupname and @ref
 * feng_srv::username, defaulting to feng:feng.
 *
 * We do not drop privileges if we're running as non-root, as in that
 * case we assume we have been given already only the limited set of
 * privileges we need.
 */
static void feng_drop_privs()
{
    const char *const wanted_group = feng_srv.groupname;
    const char *const wanted_user = feng_srv.username;

    if ( getuid() != 0 ) /* only if root */
        return;

    errno = 0;
    if ( wanted_group != NULL ) {
        struct group *gr = getgrnam(wanted_group);
        if ( errno != 0 )
            fnc_perror("getgrnam");
        else if ( gr == NULL )
            fnc_log(FNC_LOG_ERR, "%s: group %s not found", __func__, wanted_group);
        else if ( setgid(gr->gr_gid) < 0 )
            fnc_perror("setgid");
    }

    errno = 0;
    if ( wanted_user != NULL ) {
        struct passwd *pw = getpwnam(wanted_user);
        if ( errno != 0 )
            fnc_perror("getpwnam");
        else if ( pw == NULL )
            fnc_log(FNC_LOG_ERR, "%s: user %s not found", __func__, wanted_user);
        else if ( setuid(pw->pw_uid) < 0 )
            fnc_perror("setuid");
    }
}
예제 #7
0
파일: sock.c 프로젝트: dulton/hm-platform
gint
set_fd_flags(gint fd, gint flgs)
{
    gint old_flgs, err;

    old_flgs = fcntl(fd, F_GETFL, 0);
    if (G_UNLIKELY(old_flgs < 0))
    {
    	err = -errno;
    	fnc_log(FNC_LOG_ERR,
    		"set_fd_flags()->fcntl(fd, F_GETFL, 0)"
    	);
        return err;
    }

    old_flgs |= flgs;

    if (fcntl(fd, F_SETFL, old_flgs) < 0)
    {
    	err = -errno;
    	fnc_log(FNC_LOG_ERR,
    		"set_fd_flags()->fcntl(fd, F_SETFL, 0)"
    	);
        return err;
    }

    return 0;
}
예제 #8
0
파일: resource.c 프로젝트: iskey/feng_build
/**
 * @brief Read data from a resource (unlocked)
 *
 * @param resouce The resource to read from
 *
 * @return The same return value as read_packet
 */
int r_read(Resource *resource)
{
    int ret = RESOURCE_EOF;

    g_mutex_lock(resource->lock);
    if (!resource->eor)
        switch( (ret = resource->demuxer->read_packet(resource)) ) {
        case RESOURCE_OK:
            break;
        case RESOURCE_EOF:
            fnc_log(FNC_LOG_INFO,
                    "r_read_unlocked: %s read_packet() end of file.",
                    resource->info->mrl);
            resource->eor = true;
            break;
        default:
            fnc_log(FNC_LOG_FATAL,
                    "r_read_unlocked: %s read_packet() error.",
                    resource->info->mrl);
            break;
        }

    g_mutex_unlock(resource->lock);

    return ret;
}
예제 #9
0
파일: parser_h264.c 프로젝트: F35X70/feng
static char *encode_avc1_header(uint8_t *p, unsigned int len, int packet_mode)
{
    int i, cnt, nalsize;
    uint8_t *q = p;
    char *sprop = NULL;
    cnt = *(p+5) & 0x1f; // Number of sps
    p += 6;

    for (i = 0; i < cnt; i++) {
        if (p > q + len)
            goto err_alloc;
        nalsize = RB16(p); //buf_size
        p += 2;
        fnc_log(FNC_LOG_VERBOSE, "[h264] nalsize %d", nalsize);
        if (i == 0) {
            gchar *out = g_strdup_printf("profile-level-id=%02x%02x%02x; "
                                  "packetization-mode=%d; ",
                                  p[0], p[1], p[2], packet_mode);
	    gchar *buf = g_base64_encode(p, nalsize);
            sprop = g_strdup_printf("%ssprop-parameter-sets=%s", out, buf);
	    g_free(buf);
            g_free(out);
        } else {
            gchar *buf = g_base64_encode(p, nalsize);
            gchar *out = g_strdup_printf("%s,%s", sprop, buf);
            g_free(sprop);
	    g_free(buf);
            sprop = out;
        }
        p += nalsize;
    }
    // Decode pps from avcC
    cnt = *(p++); // Number of pps
    fnc_log(FNC_LOG_VERBOSE, "[h264] pps %d", cnt);

    for (i = 0; i < cnt; i++) {
        gchar *out, *buf;

        if (p > q + len)
            goto err_alloc;
        nalsize = RB16(p);
        p += 2;
        fnc_log(FNC_LOG_VERBOSE, "[h264] nalsize %d", nalsize);
	buf = g_base64_encode(p, nalsize);
        out = g_strdup_printf("%s,%s",sprop, buf);
        g_free(sprop);
	g_free(buf);
        sprop = out;
        p += nalsize;
    }

    return sprop;

    err_alloc:
        if (sprop) g_free(sprop);
    return NULL;
}
예제 #10
0
static void check_if_any_rtp_session_timedout(gpointer element,
                                              gpointer user_data)
{
    RTP_session *session = (RTP_session *)element;
    time_t *last_packet_send_time = (time_t *)user_data;
    time_t now = time(NULL);
    
    /* Jmkn: get the last packet send time in all the session*/
    if( last_packet_send_time != NULL &&
        (session->last_packet_send_time > *last_packet_send_time)){
        *last_packet_send_time = session->last_packet_send_time;
    }
    
#if 0
    /* Check if we didn't send any data for more then STREAM_BYE_TIMEOUT seconds
     * this will happen if we are not receiving any more from live producer or
     * if the stored stream ended.
     */
    if ((session->track->properties.media_source == MS_live) &&
        (now - session->last_packet_send_time) >= LIVE_STREAM_BYE_TIMEOUT) {
        fnc_log(FNC_LOG_INFO, "[client] Soft stream timeout");
        rtcp_send_sr(session, BYE);
    }

    /* If we were not able to serve any packet and the client ignored our BYE
     * kick it by closing everything
     */
    if (session->isBye != 0 && 
        (now - session->last_packet_send_time) >= STREAM_TIMEOUT) {
        fnc_log(FNC_LOG_INFO, "[client] Stream Timeout, client kicked off!");
        ev_async_send(session->srv->loop, &session->client->ev_sig_disconnect);
    }else{
#endif        
        /* send RTCP SDE */
        rtcp_send_sr(session, SDES);

        /* If we do not read RTCP	report in 12 seconds .we will deal it as the client lost
        connection,and end the child process.
        */

        if(session->srv->srvconf.rtcp_heartbeat != 0 &&
           session->last_rtcp_read_time != 0 &&
           (now - session->last_rtcp_read_time)>=60)
        {
            fnc_log(FNC_LOG_INFO, "[client] Client Lost Connection\n");
            ev_async_send(session->srv->loop, &session->client->ev_sig_disconnect);
        }
#if 0
    }
#endif
}
예제 #11
0
파일: media.c 프로젝트: dulton/hm-platform
static __inline__ gboolean
rtsp_recv_rtp_packets(RTSP_client_session *rtsp_s, RTP_Session *rtp_s,
	GEvent *ev)
{
	gchar rtp_pkt[RTP_BUFFER_LEN];
	gint rtp_size, err;

	for (;;)
	{
		rtp_size = recvfrom(g_event_fd(ev), rtp_pkt, RTP_BUFFER_LEN,
			MSG_DONTWAIT, NULL, NULL);
		if (rtp_size > 0)
		{
			RTP_Frame fr;
	
			err = rtp_parse_frame(rtp_s, rtp_pkt, rtp_size, &fr);
			if (err == RTP_PKT_OK || err == RTP_PKT_AGAIN)
			{
				if (err == RTP_PKT_OK)
				{
					INVOKE_DAT_HOOK_FRA(rtsp_s, &fr, NULL);
				}
				continue;
			}

			fnc_log(FNC_LOG_ERR,
				"[FC] Rtp parse failed, rtsp_s '%p', stop.", rtsp_s
			);

			g_event_remove_events_sync(ev, EV_READ|EV_WRITE);
			break;
		}
		else
		{
			err = -errno;
			if (err != -EAGAIN && err != -EINTR)
			{
				fnc_log(FNC_LOG_ERR,
					"[FC] Rtp recv failed, rtsp_s '%p', err:'%d', stop.", rtsp_s, err
				);
				g_event_remove_events_sync(ev, EV_READ|EV_WRITE);				
			}

			break;
		}
	}

	return TRUE;	
}
예제 #12
0
파일: demuxer.c 프로젝트: iskey/iskey
Track *add_track(Resource *r, char *name, MediaProperties *prop_hints)
{
    Track *t;

    t = g_slice_new0(Track);

    t->lock            = g_mutex_new();
    t->parent          = r;
    t->name            = name;
    t->sdp_description = g_string_new("");

    g_string_append_printf(t->sdp_description,
                           "a=control:%s\r\n",
                           name);

    memcpy(&t->properties, prop_hints, sizeof(MediaProperties));

    switch (t->properties.media_source) {
    case STORED_SOURCE:
        if ( !(t->parser = mparser_find(t->properties.encoding_name)) ) {
            fnc_log(FNC_LOG_FATAL, "Could not find a valid parser\n");
            goto error;
        }

        t->properties.media_type = t->parser->media_type;
        break;

    case LIVE_SOURCE:
        break;

    default:
        g_assert_not_reached();
        break;
    }

    if (t->parser && t->parser->init && t->parser->init(t) != 0) {
        fnc_log(FNC_LOG_FATAL, "Could not initialize parser for %s\n",
                t->properties.encoding_name);
        goto error;
    }

    r->tracks = g_list_append(r->tracks, t);

    return t;

 error:
    free_track(t, NULL);
    return NULL;
}
예제 #13
0
char *alloc_path_name(char *base_path, char *file_path)
{
  char           *PathName;
  char           *p;
  int             len;

  len = strlen(base_path);

  PathName = malloc(len + strlen(file_path) + 2);
  if (PathName==NULL) {
	  fnc_log(FNC_LOG_FATAL,"Out of memory in alloc_path_name()\n");
	  exit(-1);
  }

  p = base_path + len ; 
  if (len)
    	p--;
  if ((*p == '/') && (*file_path == '/'))
	sprintf(PathName, "%s%s", base_path, file_path + 1);
  else if ((*p != '/') && (*file_path != '/'))
	sprintf(PathName, "%s/%s", base_path, file_path);
  else
	sprintf(PathName, "%s%s", base_path, file_path);

  return (PathName);
}
예제 #14
0
파일: sock.c 프로젝트: dulton/hm-platform
static __inline__ gint 
get_new_udp_sock(gint *port)
{
	struct sockaddr_in sin;
	socklen_t len = sizeof(sin);
	gint sock, err;

	sock = unix_sock_bind(NULL, *port, L4_UDP);
	if (sock < 0)
		return sock;

	if (!*port)
	{
		if (getsockname(sock, (struct sockaddr*)&sin, &len))
		{
			err = -errno;
			fnc_log(FNC_LOG_ERR, "[FC] getsockname() failed.");			
			close(sock);
			return err;
		}
		*port = ntohs(sin.sin_port);
	}

	return sock;
}
예제 #15
0
static void interleaved_read_tcp_cb( struct ev_loop *loop, ev_io *w,
                                     int revents)
{
    GByteArray *pkt;
    uint16_t ne_n;
    char buffer[RTSP_BUFFERSIZE + 1];
    RTSP_interleaved_channel *intlvd = w->data;
    RTSP_Client *rtsp = intlvd->local->data;
    int n;

    if ((n = Sock_read(intlvd->local, buffer,
                       RTSP_BUFFERSIZE, NULL, MSG_DONTWAIT)) < 0) {
        fnc_log(FNC_LOG_WARN, "Error reading from local socket\n");
        return;
    }

    ne_n = htons((uint16_t)n);
    pkt = g_byte_array_sized_new(n+4);
    g_byte_array_set_size(pkt, n+4);

    pkt->data[0] = '$';
    pkt->data[1] = (uint8_t)intlvd->channel;
    memcpy(&pkt->data[2], &ne_n, sizeof(ne_n));
    memcpy(&pkt->data[4], buffer, n);

    g_queue_push_head(rtsp->out_queue, pkt);
    ev_io_start(rtsp->srv->loop, &rtsp->ev_io_write);
}
예제 #16
0
파일: rtp.c 프로젝트: phully/feng_build
/**
 * @brief Resume (or start) an RTP session
 *
 * @param session_gen The session to resume or start
 * @param range_gen Pointer tp @ref RTSP_Range to start with
 *
 * @todo This function should probably take care of starting eventual
 *       libev events when the scheduler is replaced.
 *
 * This function is used by the PLAY method of RTSP to start or resume
 * a session; since a newly-created session starts as paused, this is
 * the only method available.
 *
 * The use of a pointer to double rather than a double itself is to
 * make it possible to pass this function straight to foreach
 * functions from glib.
 *
 * @internal This function should only be called from g_slist_foreach.
 */
static void rtp_session_resume(gpointer session_gen, gpointer range_gen) {
    RTP_session *session = (RTP_session*)session_gen;
    RTSP_Range *range = (RTSP_Range*)range_gen;

    fnc_log(FNC_LOG_VERBOSE, "Resuming session %p\n", session);

    session->range = range;
    session->start_seq = 1 + session->seq_no;
    session->start_rtptime = g_random_int();
    session->send_time = 0.0;
    session->last_packet_send_time = time(NULL);

    /* Create the new thread pool for the read requests */
    session->fill_pool = g_thread_pool_new(rtp_session_fill_cb, session,
                                           1, true, NULL);

    /* Prefetch frames */
    rtp_session_fill(session);

    ev_periodic_set(&session->transport.rtp_writer,
                    range->playback_time - 0.05,
                    0, NULL);
    ev_periodic_start(session->srv->loop, &session->transport.rtp_writer);
    ev_io_start(session->srv->loop, &session->transport.rtcp_reader);
}
예제 #17
0
파일: rtsp_client.c 프로젝트: F35X70/feng
static void rtsp_client_free(RTSP_Client *client)
{
    GString *outbuf = NULL;
    close(client->sd);
    g_free(client->local_host);
    g_free(client->remote_host);

    rtsp_session_free(client->session);

    if ( client->channels )
        g_hash_table_destroy(client->channels);

    /* Remove the output queue */
    if ( client->out_queue ) {
        while( (outbuf = g_queue_pop_tail(client->out_queue)) )
            g_string_free(outbuf, TRUE);

        g_queue_free(client->out_queue);
    }

    if ( client->input ) /* not present on SCTP or HTTP transports */
        g_byte_array_free(client->input, true);

    g_slice_free(RFC822_Request, client->pending_request);

    g_slice_free1(client->sa_len, client->peer_sa);
    g_slice_free1(client->sa_len, client->local_sa);

    g_slice_free(RTSP_Client, client);

    fnc_log(FNC_LOG_INFO, "[client] Client removed");
}
예제 #18
0
/**
 * @brief Send an interleaved RTCP packet down to the RTCP handler
 *
 * @param rtsp The RTSP client where the handler can be found
 * @param channel The channel index where the package arrived
 * @param data The pointer to the data to send
 * @param len The length of the data to send
 *
 * This function is used to send data down to the actual RTCP handler
 * after it has been received from an interleaved transport (TCP or
 * SCTP alike).
 */
void interleaved_rtcp_send(RTSP_Client *rtsp, int channel,
                           void *data, size_t len)
{
    RTSP_interleaved *intlvd = NULL;
    GSList *intlvd_iter = g_slist_find_custom(rtsp->interleaved,
                                              GINT_TO_POINTER(channel),
                                              interleaved_rtcp_find_compare);

    /* We have to check if the value returned by g_slist_find_custom
     * is valid before derefencing it.
     */
    if ( intlvd_iter == NULL ) {
        fnc_log(FNC_LOG_DEBUG,
                "Interleaved RTCP packet arrived for unknown channel (%d)... discarding.\n",
                channel);
        return;
    }

    intlvd = (RTSP_interleaved *)intlvd_iter->data;

    /* We should be pretty sure this is not NULL */
    g_assert(intlvd != NULL);

    /* Write the actual data */
    Sock_write(intlvd->rtcp.local, data, len, NULL, MSG_DONTWAIT | MSG_EOR);
}
예제 #19
0
파일: media.c 프로젝트: dulton/hm-platform
static __inline__ RTP_Session *
rtp_session_new(RTSP_client_session *rtsp_s)
{
	RTP_Session *rtp_s;
	gint err;

	rtp_s = g_new0(RTP_Session, 1);
	rtp_s->ref_count = 1;

	if (!rtsp_s->rtp_over_rtsp)
	{
		err = rtp_session_sock_init(rtp_s);
		if (err)
		{
			fnc_log(FNC_LOG_ERR, "[FC] Init RTP sock failed, err:%d", err);
			g_free(rtp_s);
			return NULL;
		}
	}
	else
	{
		rtp_s->interleaved = 1;
		rtp_s->rtp_port = rtsp_session_get_interleaved(rtsp_s);
#ifdef CONFIG_RTCP_SUPPORT
		rtp_s->rtcp_port = rtsp_session_get_interleaved(rtsp_s);
#endif
	}

	return rtp_s;
}
예제 #20
0
static void child_terminate_cb (struct ev_loop *loop, ev_child *w, int revents)
{
    client_port_pair *client=NULL;
	pid_t pid;
	feng *srv=w->data;


    
     //ev_child_stop (EV_A_ w);
    //printf ("child process %d exited with status %x\n", w->rpid, w->rstatus);
    
    
    pid = w->rpid;
    client=get_client_list_item(pid);
    if(client)
    {
        fnc_log(FNC_LOG_INFO, 
            "The child process (pid:%d) for rtsp connection (%s:%hu) terminated with status %x\n", 
            w->rpid, 
            client->host, 
            client->port, 
            w->rstatus);    
        
        reduce_client_list(client);

        srv->connection_count--;

        free_child_port(client);

    }    
    
}
예제 #21
0
gboolean interleaved_setup_transport(RTSP_Client *rtsp, RTP_transport *transport,
                                     int rtp_ch, int rtcp_ch) {
    RTSP_interleaved *intlvd = NULL;
    Sock *sock_pair[2][2];
    //unsigned buffer_size = 0;

    // RTP local sockpair
    if ( Sock_socketpair(sock_pair[0]) < 0) {
        fnc_log(FNC_LOG_ERR,
                "Cannot create AF_LOCAL socketpair for rtp\n");
        return false;
    }

    // RTCP local sockpair
    if ( Sock_socketpair(sock_pair[1]) < 0) {
        fnc_log(FNC_LOG_ERR,
                "Cannot create AF_LOCAL socketpair for rtcp\n");
        Sock_close(sock_pair[0][0]);
        Sock_close(sock_pair[0][1]);
        return false;
    }

    intlvd = g_slice_new0(RTSP_interleaved);

    transport->rtp_sock = sock_pair[0][0];
    intlvd->rtp.local = sock_pair[0][1];
    
    /* Jmkn: Not necessary to increase the buffer for socketpair, 
     * because we send a 1.4 Kbytes packet each time
     */
/*
    buffer_size = increase_sock_buffer_to(transport->rtp_sock, SO_SNDBUF, RTP_BUF_SIZE);
    fnc_log(FNC_LOG_VERBOSE,"[rtsp] Set rtp data socket send buffer size to %u", buffer_size);
*/
    transport->rtcp_sock = sock_pair[1][0];
    intlvd->rtcp.local = sock_pair[1][1];

    // copy stream number in rtp_transport struct
    transport->rtp_ch = intlvd->rtp.channel = rtp_ch;
    transport->rtcp_ch = intlvd->rtcp.channel = rtcp_ch;

    interleaved_setup_callbacks(rtsp, intlvd);

    rtsp->interleaved = g_slist_prepend(rtsp->interleaved, intlvd);

    return true;
}
예제 #22
0
파일: parser_h264.c 프로젝트: F35X70/feng
int h264_parse(Track *tr, uint8_t *data, ssize_t len)
{
//    double nal_time; // see page 9 and 7.4.1.2
    size_t nalsize = 0, index = 0;
    uint8_t *p, *q;

    if (tr->h264.is_avc) {
        const size_t nal_length_size = tr->h264.nal_length_size;

        while (1) {
            unsigned int i;
            if(index >= len) break;
            //get the nal size
            nalsize = 0;
            for(i = 0; i < nal_length_size; i++)
                nalsize = (nalsize << 8) | data[index++];
            if(nalsize <= 1 || nalsize > len) {
                if(nalsize == 1) {
                    index++;
                    continue;
                } else {
                    fnc_log(FNC_LOG_VERBOSE, "[h264] AVC: nal size %d", nalsize);
                    break;
                }
            }
            if (DEFAULT_MTU >= nalsize) {
                struct MParserBuffer *buffer = g_slice_new0(struct MParserBuffer);

                buffer->timestamp = tr->pts;
                buffer->delivery = tr->dts;
                buffer->duration = tr->frame_duration;
                buffer->marker = true;

                buffer->data_size = nalsize;
                buffer->data = g_memdup(data + index, buffer->data_size);

                track_write(tr, buffer);

                fnc_log(FNC_LOG_VERBOSE, "[h264] single NAL");
            } else {
            // single NAL, to be fragmented, FU-A;
                frag_fu_a(data + index, nalsize, tr);
            }
            index += nalsize;
        }
    } else {
예제 #23
0
void rtsp_interleaved_receive(RTSP_Client *rtsp, int channel, uint8_t *data, size_t len)
{
    RTP_session *rtp = NULL;

    if ( (rtp = g_hash_table_lookup(rtsp->channels, GINT_TO_POINTER(channel))) == NULL )
        fnc_log(FNC_LOG_INFO, "Received interleaved message for unknown channel %d", channel);
    else /* we currently only support inbound RTCP; find a solution before supporting inbound RTP */
        rtcp_handle(rtp, data, len);
}
예제 #24
0
파일: parser_h264.c 프로젝트: F35X70/feng
static void frag_fu_a(uint8_t *nal, int fragsize, Track *tr)
{
    int start = 1;
    const uint8_t fu_indicator = (nal[0] & 0xe0) | 28;
    const uint8_t fu_header = nal[0] & 0x1f;

    fnc_log(FNC_LOG_VERBOSE, "[h264] frags");

    nal++;
    fragsize--;

    while(fragsize>0) {
        const size_t fraglen = MIN(DEFAULT_MTU-2, fragsize);
        struct MParserBuffer *buffer = g_slice_new0(struct MParserBuffer);

        buffer->timestamp = tr->pts;
        buffer->delivery = tr->dts;
        buffer->duration = tr->frame_duration;

        buffer->data_size = fraglen + 2;
        buffer->data = g_malloc(buffer->data_size);

        buffer->data[0] = fu_indicator;
        buffer->data[1] = fu_header;

        if ( start ) {
            buffer->data[1] |= (1<<7);
            start = 0;
        }

        if (fraglen == fragsize) {
            buffer->marker = true;
            buffer->data[1] |= (1<<6);
        }

        memcpy(buffer->data + 2, nal, fraglen);
        fnc_log(FNC_LOG_VERBOSE, "[h264] Frag %02x%02x", buffer->data[0], buffer->data[1]);

        track_write(tr, buffer);

        fragsize -= fraglen;
        nal      += fraglen;
    }
}
예제 #25
0
파일: rtp.c 프로젝트: phully/feng_build
/**
 * @brief parse incoming RTCP packets
 */
static void rtcp_read_cb(ATTR_UNUSED struct ev_loop *loop,
                         ev_io *w,
                         ATTR_UNUSED int revents)
{
    char buffer[RTP_DEFAULT_MTU*2] = { 0, }; //FIXME just a quick hack...
    RTP_session *session = w->data;
    int n = Sock_read(session->transport.rtcp_sock, buffer,
                      RTP_DEFAULT_MTU*2, NULL, 0);
    fnc_log(FNC_LOG_INFO, "[RTCP] Read %d byte", n);
}
예제 #26
0
int send_reply(int err, char *addon, RTSP_buffer * rtsp)
{
	unsigned int len;
	char *b;
	char *p;
	int res;
	char method[32];
	char object[256];
	char ver[32];


	if (addon != NULL) {
		len = 256 + strlen(addon);
	} else {
		len = 256;
	}

	b = (char *) malloc(len);
	if (b == NULL) {
		fnc_log(FNC_LOG_ERR,"send_reply(): memory allocation error.\n");
		return ERR_ALLOC;
	}
	memset(b, 0, sizeof(b));
	sprintf(b, "%s %d %s"RTSP_EL"CSeq: %d"RTSP_EL, RTSP_VER, err, get_stat(err), rtsp->rtsp_cseq);
	//---patch coerenza con rfc in caso di errore
	// strcat(b, "\r\n");
	strcat(b, RTSP_EL);

	res = bwrite(b, (unsigned short) strlen(b), rtsp);
	free(b);
	
	sscanf(rtsp->in_buffer, " %31s %255s %31s ", method, object, ver);
	fnc_log(FNC_LOG_ERR,"%s %s %s %d - - ", method, object, ver, err);
	if ((p=strstr(rtsp->in_buffer, HDR_USER_AGENT))!=NULL) {
		char cut[strlen(p)];
		strcpy(cut,p);
		cut[strlen(cut)-1]='\0';
		fnc_log(FNC_LOG_CLIENT,"%s",cut);
	}
	
	return res;
}
예제 #27
0
파일: media.c 프로젝트: dulton/hm-platform
static __inline__ void
rtp_session_destroy_ssrc(RTP_Session *rtp_s)
{
	if (rtp_s->ssrc != &rtp_s->rtp_ssrc_init)
	{
		fnc_log(FNC_LOG_ERR, "[FC] rtp ssrc sanity check failed!");
		BUG();
	}

	return;
}
예제 #28
0
int send_options_reply(RTSP_buffer * rtsp, long cseq)
{
	char r[1024];
	sprintf(r, "%s %d %s"RTSP_EL"CSeq: %ld"RTSP_EL, RTSP_VER, 200, get_stat(200), cseq);
	strcat(r, "Public: OPTIONS,DESCRIBE,SETUP,PLAY,PAUSE,TEARDOWN"RTSP_EL);
	strcat(r, RTSP_EL);
	bwrite(r, (unsigned short) strlen(r), rtsp);
	
	fnc_log(FNC_LOG_CLIENT,"200 - - ");

	return ERR_NOERROR;
}
예제 #29
0
파일: rtp.c 프로젝트: dulton/hm-platform
static void
rtp_packet_send(RTP_session *session, MParserBuffer *buffer, time_t time_now)
{
    gsize packet_size = sizeof(RTP_packet) + buffer->data_size;
    RTP_packet *packet = g_malloc0(packet_size);
    Track *tr = session->track;
    guint32 timestamp = RTP_calc_rtptime(session,
                                         tr->properties.clock_rate,
                                         buffer);

    packet->version = 2;
    packet->padding = 0;
    packet->extension = 0;
    packet->csrc_len = 0;
    packet->marker = buffer->marker & 0x1;
    packet->payload = tr->properties.payload_type & 0x7f;
    packet->seq_no = htons(++session->seq_no);
    packet->timestamp = htonl(timestamp);
    packet->ssrc = htonl(session->ssrc);

    fnc_log(FNC_LOG_VERBOSE, "[RTP] Timestamp: %u", ntohl(timestamp));

    memcpy(packet->data, buffer->data, buffer->data_size);

	if (__rtp_pkt_send(session, &session->transport, 
		packet, packet_size) < 0)
	{
        fnc_log(FNC_LOG_DEBUG, "RTP Packet Lost\n");		
	}
    else
    {
        session->last_timestamp = buffer->timestamp;
        session->pkt_count++;
        session->octet_count += buffer->data_size;

        session->last_packet_send_time = time_now;//time(NULL);
    }

    g_free(packet);
}
예제 #30
0
파일: main.c 프로젝트: F35X70/feng
static void command_environment(int argc, char **argv)
{
#ifndef CLEANUP_DESTRUCTOR
    gchar *progname;
#endif
    gchar *config_file = NULL;
    gboolean quiet = FALSE, verbose = FALSE, lint = FALSE;

    GOptionEntry optionsTable[] = {
        { "config", 'f', 0, G_OPTION_ARG_STRING, &config_file,
            "specify configuration file", NULL },
        { "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
            "show as little output as possible", NULL },
        { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
            "output to standard error (debug)", NULL },
        { "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version,
            "print version information and exit", NULL },
        { "lint", 'l', 0, G_OPTION_ARG_NONE, &lint,
          "check the configuration file for errors, then exit", NULL },
        { NULL, 0, 0, 0, NULL, NULL, NULL }
    };

    GError *error = NULL;
    GOptionContext *context = g_option_context_new("");
    g_option_context_add_main_entries(context, optionsTable, PACKAGE_TARNAME);

    g_option_context_parse(context, &argc, &argv, &error);
    g_option_context_free(context);

    if ( error != NULL ) {
        fnc_log(FNC_LOG_FATAL, "%s", error->message);
        exit(1);
    }

    if (!quiet && !lint) fncheader();

    config_file_parse(config_file, lint);

    g_free(config_file);

    /* if we're doing a verbose run, make sure to output
       everything directly on standard error.
    */
    if ( verbose ) {
        feng_srv.log_level = FNC_LOG_INFO;
        feng_srv.error_log = "stderr";
    }

    progname = g_path_get_basename(argv[0]);

    fnc_log_init(progname);
}