mirror of
https://github.com/drasko/open-ameba.git
synced 2024-11-22 05:54:17 +00:00
add
This commit is contained in:
parent
3c4de184c7
commit
265d41b6a3
15 changed files with 4684 additions and 1185 deletions
98
RTL00_SDKV35a/component/common/example/mcast/example_mcast.c
Normal file
98
RTL00_SDKV35a/component/common/example/mcast/example_mcast.c
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include <platform/platform_stdlib.h>
|
||||||
|
|
||||||
|
#include <lwip/sockets.h>
|
||||||
|
#include <lwip_netconf.h>
|
||||||
|
#include <lwip/netif.h>
|
||||||
|
extern struct netif xnetif[];
|
||||||
|
|
||||||
|
static void example_mcast_thread(void *param)
|
||||||
|
{
|
||||||
|
#if LWIP_IGMP
|
||||||
|
int err = 0;
|
||||||
|
int socket = -1;
|
||||||
|
char *group_ip = "224.0.0.251";
|
||||||
|
uint16_t port = 5353;
|
||||||
|
|
||||||
|
// Set NETIF_FLAG_IGMP flag for netif which should process IGMP messages
|
||||||
|
xnetif[0].flags |= NETIF_FLAG_IGMP;
|
||||||
|
|
||||||
|
if((socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||||
|
printf("ERROR: socket - AF_INET, SOCK_DGRAM\n");
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add multicast group membership on this interface
|
||||||
|
if(err == 0) {
|
||||||
|
struct ip_mreq imr;
|
||||||
|
imr.imr_multiaddr.s_addr = inet_addr(group_ip);
|
||||||
|
imr.imr_interface.s_addr = INADDR_ANY;
|
||||||
|
err = setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr));
|
||||||
|
if(err < 0) printf("ERROR: setsockopt - IP_ADD_MEMBERSHIP\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specify outgoing interface too
|
||||||
|
if(err == 0) {
|
||||||
|
struct in_addr intfAddr;
|
||||||
|
intfAddr.s_addr = INADDR_ANY;
|
||||||
|
err = setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &intfAddr, sizeof(struct in_addr));
|
||||||
|
if(err < 0) printf("ERROR: setsockopt - IP_MULTICAST_IF\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// And start listening for packets
|
||||||
|
if(err == 0) {
|
||||||
|
struct sockaddr_in bindAddr;
|
||||||
|
bindAddr.sin_family = AF_INET;
|
||||||
|
bindAddr.sin_port = htons(port);
|
||||||
|
bindAddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
err = bind(socket, (struct sockaddr *) &bindAddr, sizeof(bindAddr));
|
||||||
|
if(err < 0) printf("ERROR: bind\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(err == 0) {
|
||||||
|
unsigned char packet[1024];
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
// Receive multicast
|
||||||
|
int packetLen;
|
||||||
|
struct sockaddr from;
|
||||||
|
struct sockaddr_in *from_sin = (struct sockaddr_in*) &from;
|
||||||
|
socklen_t fromLen = sizeof(from);
|
||||||
|
|
||||||
|
if((packetLen = recvfrom(socket, &packet, sizeof(packet), 0, &from, &fromLen)) >= 0) {
|
||||||
|
uint8_t *ip = (uint8_t *) &from_sin->sin_addr.s_addr;
|
||||||
|
uint16_t from_port = ntohs(from_sin->sin_port);
|
||||||
|
printf("recvfrom - %d bytes from %d.%d.%d.%d:%d\n", packetLen, ip[0], ip[1], ip[2], ip[3], from_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send multicast
|
||||||
|
if(packetLen > 0) {
|
||||||
|
int sendLen;
|
||||||
|
struct sockaddr to;
|
||||||
|
struct sockaddr_in *to_sin = (struct sockaddr_in*) &to;
|
||||||
|
to_sin->sin_family = AF_INET;
|
||||||
|
to_sin->sin_port = htons(port);
|
||||||
|
to_sin->sin_addr.s_addr = inet_addr(group_ip);
|
||||||
|
|
||||||
|
if((sendLen = sendto(socket, packet, packetLen, 0, &to, sizeof(struct sockaddr))) < 0)
|
||||||
|
printf("ERROR: sendto %s\n", group_ip);
|
||||||
|
else
|
||||||
|
printf("sendto - %d bytes to %s:%d\n", sendLen, group_ip, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(socket != -1) {
|
||||||
|
close(socket);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
printf("\nSHOULD ENABLE LWIP_IGMP\n");
|
||||||
|
#endif
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void example_mcast(void)
|
||||||
|
{
|
||||||
|
if(xTaskCreate(example_mcast_thread, ((const char*)"example_mcast_thread"), 2048, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS)
|
||||||
|
printf("\n\r%s xTaskCreate(init_thread) failed", __FUNCTION__);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef EXAMPLE_MCAST_H
|
||||||
|
#define EXAMPLE_MCAST_H
|
||||||
|
|
||||||
|
void example_mcast(void);
|
||||||
|
|
||||||
|
#endif /* EXAMPLE_MCAST_H */
|
17
RTL00_SDKV35a/component/common/example/mcast/readme.txt
Normal file
17
RTL00_SDKV35a/component/common/example/mcast/readme.txt
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
LWIP MULTICAST EXAMPLE
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Join multicast group of 224.0.0.251 and listen on port 5353.
|
||||||
|
Send packet with the content of received packet to multicast group of 224.0.0.251.
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
[lwipopts.h]
|
||||||
|
#define LWIP_UDP 1
|
||||||
|
#define LWIP_IGMP 1
|
||||||
|
[platform_opts.h]
|
||||||
|
#define CONFIG_EXAMPLE_MCAST 1
|
||||||
|
|
||||||
|
Execution:
|
||||||
|
Can make automatical Wi-Fi connection when booting by using wlan fast connect example.
|
||||||
|
A multicast example thread will be started automatically when booting.
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <task.h>
|
||||||
|
#include <platform/platform_stdlib.h>
|
||||||
|
|
||||||
|
#include <lwip/sockets.h>
|
||||||
|
#include <polarssl/config.h>
|
||||||
|
#include <polarssl/memory.h>
|
||||||
|
#include <polarssl/ssl.h>
|
||||||
|
|
||||||
|
#define SERVER_HOST "192.168.13.27"
|
||||||
|
#define SERVER_PORT 443
|
||||||
|
#define RESOURCE "/dummy100k.bin"
|
||||||
|
|
||||||
|
static unsigned int arc4random(void)
|
||||||
|
{
|
||||||
|
unsigned int res = xTaskGetTickCount();
|
||||||
|
static unsigned int seed = 0xDEADB00B;
|
||||||
|
|
||||||
|
seed = ((seed & 0x007F00FF) << 7) ^
|
||||||
|
((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits
|
||||||
|
(res << 13) ^ (res >> 9); // using the clock too!
|
||||||
|
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_random_bytes(void *buf, size_t len)
|
||||||
|
{
|
||||||
|
unsigned int ranbuf;
|
||||||
|
unsigned int *lp;
|
||||||
|
int i, count;
|
||||||
|
count = len / sizeof(unsigned int);
|
||||||
|
lp = (unsigned int *) buf;
|
||||||
|
|
||||||
|
for(i = 0; i < count; i ++) {
|
||||||
|
lp[i] = arc4random();
|
||||||
|
len -= sizeof(unsigned int);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len > 0) {
|
||||||
|
ranbuf = arc4random();
|
||||||
|
memcpy(&lp[i], &ranbuf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int my_random(void *p_rng, unsigned char *output, size_t output_len)
|
||||||
|
{
|
||||||
|
get_random_bytes(output, output_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void example_ssl_download_thread(void *param)
|
||||||
|
{
|
||||||
|
int server_fd = -1, ret;
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
ssl_context ssl;
|
||||||
|
|
||||||
|
// Delay to wait for IP by DHCP
|
||||||
|
vTaskDelay(10000);
|
||||||
|
printf("\nExample: SSL download\n");
|
||||||
|
|
||||||
|
memory_set_own(pvPortMalloc, vPortFree);
|
||||||
|
memset(&ssl, 0, sizeof(ssl_context));
|
||||||
|
|
||||||
|
if((ret = net_connect(&server_fd, SERVER_HOST, SERVER_PORT)) != 0) {
|
||||||
|
printf("ERROR: net_connect ret(%d)\n", ret);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((ret = ssl_init(&ssl)) != 0) {
|
||||||
|
printf("ERRPR: ssl_init ret(%d)\n", ret);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
|
||||||
|
ssl_set_authmode(&ssl, SSL_VERIFY_NONE);
|
||||||
|
ssl_set_rng(&ssl, my_random, NULL);
|
||||||
|
ssl_set_bio(&ssl, net_recv, &server_fd, net_send, &server_fd);
|
||||||
|
|
||||||
|
if((ret = ssl_handshake(&ssl)) != 0) {
|
||||||
|
printf("ERROR: ssl_handshake ret(-0x%x)", -ret);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unsigned char buf[2048];
|
||||||
|
int read_size = 0, resource_size = 0, content_len = 0, header_removed = 0;
|
||||||
|
|
||||||
|
printf("SSL ciphersuite %s\n", ssl_get_ciphersuite(&ssl));
|
||||||
|
sprintf(buf, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", RESOURCE, SERVER_HOST);
|
||||||
|
ssl_write(&ssl, buf, strlen(buf));
|
||||||
|
|
||||||
|
while((read_size = ssl_read(&ssl, buf, sizeof(buf))) > 0) {
|
||||||
|
if(header_removed == 0) {
|
||||||
|
char *header = strstr(buf, "\r\n\r\n");
|
||||||
|
|
||||||
|
if(header) {
|
||||||
|
char *body, *content_len_pos;
|
||||||
|
|
||||||
|
body = header + strlen("\r\n\r\n");
|
||||||
|
*(body - 2) = 0;
|
||||||
|
header_removed = 1;
|
||||||
|
printf("\nHTTP Header: %s\n", buf);
|
||||||
|
read_size = read_size - ((unsigned char *) body - buf);
|
||||||
|
|
||||||
|
content_len_pos = strstr(buf, "Content-Length: ");
|
||||||
|
if(content_len_pos) {
|
||||||
|
content_len_pos += strlen("Content-Length: ");
|
||||||
|
*(strstr(content_len_pos, "\r\n")) = 0;
|
||||||
|
content_len = atoi(content_len_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("ERROR: HTTP header\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("read resource %d bytes\n", read_size);
|
||||||
|
resource_size += read_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("final read size = %d bytes\n", read_size);
|
||||||
|
printf("http content-length = %d bytes, download resource size = %d bytes\n", content_len, resource_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if(server_fd != -1)
|
||||||
|
net_close(server_fd);
|
||||||
|
|
||||||
|
ssl_free(&ssl);
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void example_ssl_download(void)
|
||||||
|
{
|
||||||
|
if(xTaskCreate(example_ssl_download_thread, ((const char*)"example_ssl_download_thread"), 2048, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS)
|
||||||
|
printf("\n\r%s xTaskCreate(init_thread) failed", __FUNCTION__);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef EXAMPLE_SSL_DOWNLOAD_H
|
||||||
|
#define EXAMPLE_SSL_DOWNLOAD_H
|
||||||
|
|
||||||
|
void example_ssl_download(void);
|
||||||
|
|
||||||
|
#endif /* EXAMPLE_SSL_DOWNLOAD_H */
|
|
@ -0,0 +1,16 @@
|
||||||
|
SSL DOWNLOAD EXAMPLE
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Download file from Web server via https.
|
||||||
|
|
||||||
|
Configuration:
|
||||||
|
Modify SSL_MAX_CONTENT_LEN in SSL config and configTOTAL_HEAP_SIZE in freertos config for large size file
|
||||||
|
Modify SERVER_HOST, SERVER_PORT and RESOURCE in example_ssl_download.c based on your SSL server
|
||||||
|
|
||||||
|
[platform_opts.h]
|
||||||
|
#define CONFIG_EXAMPLE_SSL_DOWNLOAD 1
|
||||||
|
|
||||||
|
Execution:
|
||||||
|
Can make automatical Wi-Fi connection when booting by using wlan fast connect example.
|
||||||
|
A ssl download example thread will be started automatically when booting.
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
|
||||||
|
#include "example_uart_update.h"
|
||||||
|
|
||||||
|
int is_update_image_enable(gpio_t *gpio_uart_update_eable)
|
||||||
|
{
|
||||||
|
|
||||||
|
HAL_GPIO_PIN GPIO_Pin;
|
||||||
|
u32 active_state;
|
||||||
|
// gpio_t gpio_uart_update_eable;
|
||||||
|
int ret = 0;
|
||||||
|
#if 0
|
||||||
|
GPIO_Pin.pin_name = 0xC4;
|
||||||
|
//low active
|
||||||
|
GPIO_Pin.pin_mode = DIN_PULL_HIGH;
|
||||||
|
active_state = GPIO_PIN_LOW;
|
||||||
|
|
||||||
|
HAL_GPIO_Init(&GPIO_Pin);
|
||||||
|
|
||||||
|
if (HAL_GPIO_ReadPin(&GPIO_Pin) == active_state)
|
||||||
|
ret = 0;
|
||||||
|
else
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
HAL_GPIO_DeInit(&GPIO_Pin);
|
||||||
|
#else
|
||||||
|
gpio_init(gpio_uart_update_eable, PIN_NAME);
|
||||||
|
gpio_dir(gpio_uart_update_eable, PIN_INPUT); // Direction: Input
|
||||||
|
gpio_mode(gpio_uart_update_eable, PullUp); // Pull-High
|
||||||
|
// ret = gpio_read(&gpio_uart_update_eable);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
void example_uart_update_thread(void *param)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
gpio_t gpio_uart_update_eable;
|
||||||
|
|
||||||
|
is_update_image_enable(&gpio_uart_update_eable);
|
||||||
|
//polling MAX_WAIT_TIME*50ms
|
||||||
|
while(count <= MAX_WAIT_TIME)
|
||||||
|
{
|
||||||
|
printf(" waitting update enable\r\n");
|
||||||
|
if(gpio_read(&gpio_uart_update_eable) == 0){
|
||||||
|
printf(" update image enabled!\r\n");
|
||||||
|
uart_ymodem();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
RtlMsleepOS(50);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void example_uart_update(void)
|
||||||
|
{
|
||||||
|
if(xTaskCreate(example_uart_update_thread, ((const char*)"example_uart_update_thread"), 512, NULL, tskIDLE_PRIORITY + 2, NULL) != pdPASS)
|
||||||
|
printf("\n\r%s xTaskCreate(init_thread) failed", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef UART_UPDATE_H
|
||||||
|
#define UART_UPDATE_H
|
||||||
|
|
||||||
|
#include "PinNames.h"
|
||||||
|
#include "gpio_api.h"
|
||||||
|
#include "hal_gpio.h"
|
||||||
|
#include "osdep_api.h"
|
||||||
|
|
||||||
|
#define PIN_NAME PC_2
|
||||||
|
#define MAX_WAIT_TIME 100
|
||||||
|
|
||||||
|
void example_uart_update();
|
||||||
|
int is_update_image_enable(gpio_t *gpio_uart_update_eable);
|
||||||
|
extern int uart_ymodem(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
586
RTL00_SDKV35a/component/common/example/uvc/example_uvc.c
Normal file
586
RTL00_SDKV35a/component/common/example/uvc/example_uvc.c
Normal file
|
@ -0,0 +1,586 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* V4L2 video capture example
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "example_uvc.h"
|
||||||
|
#include "videodev2.h"
|
||||||
|
#include "uvcvideo.h"
|
||||||
|
#include "v4l2_driver.h"
|
||||||
|
#include "mjpeg/mjpeg.h"
|
||||||
|
#include "rtsp/rtsp_api.h"
|
||||||
|
#include "sockets.h"
|
||||||
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
|
#include "uvc_intf.h"
|
||||||
|
|
||||||
|
#include "section_config.h"
|
||||||
|
SDRAM_DATA_SECTION struct rtp_object rtp_payload[VIDEO_MAX_FRAME];
|
||||||
|
|
||||||
|
struct rtp_payload_queue payload_queue;
|
||||||
|
|
||||||
|
void example_uvc(void)
|
||||||
|
{
|
||||||
|
/*init payload queue*/
|
||||||
|
INIT_LIST_HEAD(&payload_queue.wait_queue);
|
||||||
|
INIT_LIST_HEAD(&payload_queue.done_queue);
|
||||||
|
RtlMutexInit(&payload_queue.wait_mutex);
|
||||||
|
RtlMutexInit(&payload_queue.done_mutex);
|
||||||
|
RtlInitSema(&payload_queue.wait_sema, 0);
|
||||||
|
RtlInitSema(&payload_queue.done_sema, 0);
|
||||||
|
payload_queue.flush_err = 0;
|
||||||
|
uvc_stream_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uvc_entry_handle(void *param)
|
||||||
|
{
|
||||||
|
int i, ret, cnt;
|
||||||
|
struct stream_context *stream_ctx = (struct stream_context *)param;
|
||||||
|
struct uvc_buf_context buf;
|
||||||
|
struct rtp_object *payload;
|
||||||
|
|
||||||
|
/*initialize rtp payload*/
|
||||||
|
for(i = 0; i < VIDEO_MAX_FRAME; i++)
|
||||||
|
{
|
||||||
|
if(rtp_init_payload(stream_ctx, &rtp_payload[i]) < 0)
|
||||||
|
{
|
||||||
|
for(; i>=0; i--)
|
||||||
|
{
|
||||||
|
rtp_uninit_payload(stream_ctx, &rtp_payload[i]);
|
||||||
|
}
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(uvc_set_param(stream_ctx, UVC_FORMAT_MJPEG, 640, 480, 30)<0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if(uvc_stream_on(stream_ctx)<0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/*do buffer queue & dequeue inside the loop*/
|
||||||
|
payload_queue.flush_err = 0;
|
||||||
|
while(!(payload_queue.flush_err))
|
||||||
|
{
|
||||||
|
memset(&buf, 0, sizeof(struct uvc_buf_context));
|
||||||
|
ret = uvc_dqbuf(stream_ctx, &buf);
|
||||||
|
if(buf.index < 0)
|
||||||
|
continue;//empty buffer retrieved
|
||||||
|
if((uvc_buf_check(&buf)<0)||(ret < 0)){
|
||||||
|
RTSP_ERROR("\n\rbuffer error!");
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
rtp_payload[buf.index].index = buf.index;
|
||||||
|
if(rtp_fill_payload(stream_ctx, &rtp_payload[buf.index], buf.data, buf.len) < 0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/*add rtp_payload into payload queue*/
|
||||||
|
RtlDownMutex(&payload_queue.wait_mutex);
|
||||||
|
list_add_tail(&rtp_payload[buf.index].rtp_list, &payload_queue.wait_queue);
|
||||||
|
RtlUpMutex(&payload_queue.wait_mutex);
|
||||||
|
RtlUpSema(&payload_queue.wait_sema);
|
||||||
|
|
||||||
|
//check if any rtp payload is queued in done_queue
|
||||||
|
while(RtlDownSemaWithTimeout(&payload_queue.done_sema, 5)==0)
|
||||||
|
{
|
||||||
|
if(payload_queue.flush_err)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if(!list_empty(&payload_queue.done_queue))
|
||||||
|
{
|
||||||
|
RtlDownMutex(&payload_queue.done_mutex);
|
||||||
|
payload = list_first_entry(&payload_queue.done_queue, struct rtp_object, rtp_list);
|
||||||
|
if(payload == NULL)
|
||||||
|
{
|
||||||
|
RtlUpMutex(&payload_queue.done_mutex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list_del_init(&payload->rtp_list);
|
||||||
|
RtlUpMutex(&payload_queue.done_mutex);
|
||||||
|
|
||||||
|
buf.index = payload->index;
|
||||||
|
buf.data = payload->data;
|
||||||
|
buf.len = payload->len;
|
||||||
|
|
||||||
|
ret = uvc_qbuf(stream_ctx, &buf);
|
||||||
|
if (ret < 0){
|
||||||
|
RTSP_ERROR("\n\rread_frame mmap method enqueue buffer failed");
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
uvc_stream_off(stream_ctx);
|
||||||
|
uvc_stream_free(stream_ctx);
|
||||||
|
|
||||||
|
for(i = 0; i < VIDEO_MAX_FRAME; i++)
|
||||||
|
{
|
||||||
|
rtp_uninit_payload(stream_ctx, &rtp_payload[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//free payload_queue memory
|
||||||
|
INIT_LIST_HEAD(&payload_queue.wait_queue);
|
||||||
|
INIT_LIST_HEAD(&payload_queue.done_queue);
|
||||||
|
RtlMutexFree(&payload_queue.wait_mutex);
|
||||||
|
RtlMutexFree(&payload_queue.done_mutex);
|
||||||
|
RtlFreeSema(&payload_queue.wait_sema);
|
||||||
|
RtlFreeSema(&payload_queue.done_sema);
|
||||||
|
|
||||||
|
printf("\n\rstream free success, delete task...");
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int uvc_rtp_init(struct rtsp_context *rtsp_ctx);
|
||||||
|
void uvc_rtsp_handle(void *param)
|
||||||
|
{
|
||||||
|
struct stream_context *stream_ctx = (struct stream_context *)param;
|
||||||
|
struct rtsp_context *rtsp_ctx;
|
||||||
|
u8 *request_header; //buffer to hold rtsp request
|
||||||
|
struct sockaddr_in server_addr, client_addr;
|
||||||
|
int client_socket;
|
||||||
|
socklen_t client_addr_len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
fd_set read_fds;
|
||||||
|
struct timeval timeout;
|
||||||
|
int ok;
|
||||||
|
rtsp_ctx = malloc(sizeof(struct rtsp_context));
|
||||||
|
if(rtsp_ctx == NULL)
|
||||||
|
{
|
||||||
|
RTSP_ERROR("\n\rrtsp context is NULL");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
request_header = malloc(512);
|
||||||
|
if(request_header == NULL)
|
||||||
|
{
|
||||||
|
RTSP_ERROR("\n\rallocate request header buffer failed");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
// Delay to wait for IP by DHCP
|
||||||
|
vTaskDelay(500);
|
||||||
|
/*init rtsp context to unicast udp mode*/
|
||||||
|
if(rtsp_context_init(rtsp_ctx) < 0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
server_addr.sin_family = AF_INET;
|
||||||
|
server_addr.sin_addr.s_addr = *(uint32_t *)(rtsp_ctx->connect_ctx.server_ip)/*htonl(INADDR_ANY)*/;
|
||||||
|
server_addr.sin_port = htons(rtsp_ctx->connect_ctx.port);
|
||||||
|
|
||||||
|
if(bind(rtsp_ctx->connect_ctx.socket_id, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
|
||||||
|
RTSP_ERROR("\n\rCannot bind stream socket");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
listen(rtsp_ctx->connect_ctx.socket_id, 1);
|
||||||
|
printf("\n\rrtsp context initialized!");
|
||||||
|
|
||||||
|
stream_ctx->protoCtx = (void *)rtsp_ctx;
|
||||||
|
rtsp_ctx->stream_ctx = (void *)stream_ctx;
|
||||||
|
|
||||||
|
/*start rtp task*/
|
||||||
|
uvc_rtp_init(rtsp_ctx);
|
||||||
|
|
||||||
|
|
||||||
|
while(stream_ctx->allowStream)
|
||||||
|
{
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
FD_SET(rtsp_ctx->connect_ctx.socket_id, &read_fds);
|
||||||
|
if(select(1, &read_fds, NULL, NULL, &timeout))
|
||||||
|
{
|
||||||
|
client_socket = accept(rtsp_ctx->connect_ctx.socket_id,(struct sockaddr *)&client_addr, &client_addr_len);
|
||||||
|
if(client_socket < 0)
|
||||||
|
{
|
||||||
|
RTSP_ERROR("client_socket error:%d\r\n", client_socket);
|
||||||
|
close(client_socket);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*(rtsp_ctx->connect_ctx.remote_ip + 3) = (unsigned char) (client_addr.sin_addr.s_addr >> 24);
|
||||||
|
*(rtsp_ctx->connect_ctx.remote_ip + 2) = (unsigned char) (client_addr.sin_addr.s_addr >> 16);
|
||||||
|
*(rtsp_ctx->connect_ctx.remote_ip + 1) = (unsigned char) (client_addr.sin_addr.s_addr >> 8);
|
||||||
|
*(rtsp_ctx->connect_ctx.remote_ip) = (unsigned char) (client_addr.sin_addr.s_addr );
|
||||||
|
|
||||||
|
while(stream_ctx->allowStream)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
read(client_socket, request_header, 512);
|
||||||
|
rtsp_readheader(request_header);
|
||||||
|
if(*request_header == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
//Do I need to send error response to client?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rtsp_getparam(rtsp_ctx, request_header);
|
||||||
|
switch(rtsp_ctx->rtsp_cmd)
|
||||||
|
{
|
||||||
|
|
||||||
|
case(CMD_OPTIONS):
|
||||||
|
RTSP_PRINTF("\n\rReceive options command!");
|
||||||
|
if(rtsp_ctx->state == RTSP_PLAYING)
|
||||||
|
break;
|
||||||
|
|
||||||
|
rtsp_cmd_options(rtsp_ctx);
|
||||||
|
ok = write(client_socket, rtsp_ctx->response, strlen(rtsp_ctx->response));
|
||||||
|
if (ok <= 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
RTSP_ERROR("\n\rsend OPTIONS response failed!");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
case(CMD_DESCRIBE):
|
||||||
|
RTSP_PRINTF("\n\rReceive describe command!");
|
||||||
|
if(rtsp_ctx->state == RTSP_PLAYING)
|
||||||
|
break;
|
||||||
|
|
||||||
|
rtsp_cmd_describe(rtsp_ctx);
|
||||||
|
ok = write(client_socket, rtsp_ctx->response, strlen(rtsp_ctx->response));
|
||||||
|
if (ok <= 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
RTSP_ERROR("\n\rsend DESCRIBE response failed!");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
case(CMD_SETUP):
|
||||||
|
RTSP_PRINTF("\n\rReceive setup command!");
|
||||||
|
if(rtsp_ctx->state == RTSP_PLAYING)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//fill transport parameter
|
||||||
|
rtsp_cmd_setup(rtsp_ctx);
|
||||||
|
ok = write(client_socket, rtsp_ctx->response, strlen(rtsp_ctx->response));
|
||||||
|
if (ok <= 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
RTSP_ERROR("\n\rsend SETUP response failed!");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(rtsp_ctx->state == RTSP_INIT)
|
||||||
|
{
|
||||||
|
|
||||||
|
rtsp_ctx->state = RTSP_READY;
|
||||||
|
RTSP_PRINTF("\n\rstate changed from RTSP_INIT to RTSP_READY");
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case(CMD_TEARDOWN):
|
||||||
|
RTSP_PRINTF("\n\rReceive teardown command!");
|
||||||
|
rtsp_ctx->state = RTSP_INIT;
|
||||||
|
rtsp_cmd_teardown(rtsp_ctx);
|
||||||
|
ok = write(client_socket, rtsp_ctx->response, strlen(rtsp_ctx->response));
|
||||||
|
if (ok <= 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
RTSP_ERROR("\n\rsend TEARDOWN response failed!");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RTSP_PRINTF("\n\rstreaming teardown, state changed back to RTSP_INIT");
|
||||||
|
/*have to wait until rtp server reinit*/
|
||||||
|
vTaskDelay(1000);
|
||||||
|
goto out;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case(CMD_PLAY):
|
||||||
|
RTSP_PRINTF("\n\rReceive play command!");
|
||||||
|
if(rtsp_ctx->state == RTSP_PLAYING)
|
||||||
|
break;
|
||||||
|
|
||||||
|
rtsp_cmd_play(rtsp_ctx);
|
||||||
|
ok = write(client_socket, rtsp_ctx->response, strlen(rtsp_ctx->response));
|
||||||
|
if (ok <= 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
RTSP_ERROR("\n\rsend PLAY response failed!");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(rtsp_ctx->state == RTSP_READY)
|
||||||
|
{
|
||||||
|
|
||||||
|
rtsp_ctx->state = RTSP_PLAYING;
|
||||||
|
RTSP_PRINTF("\n\rstate changed from RTSP_READY to RTSP_PLAYING");
|
||||||
|
rtsp_ctx->is_rtp_start = 1;
|
||||||
|
RtlUpSema(&rtsp_ctx->start_rtp_sema);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
case(CMD_PAUSE):
|
||||||
|
RTSP_PRINTF("\n\rReceive pause command!");
|
||||||
|
rtsp_cmd_pause(rtsp_ctx);
|
||||||
|
ok = write(client_socket, rtsp_ctx->response, strlen(rtsp_ctx->response));
|
||||||
|
if (ok <= 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
RTSP_ERROR("\n\rsend PAUSE response failed!");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(rtsp_ctx->state == RTSP_PLAYING)
|
||||||
|
{
|
||||||
|
|
||||||
|
rtsp_ctx->state = RTSP_READY;
|
||||||
|
RTSP_PRINTF("\n\rstate changed from RTSP_PLAYING to RTSP_READY");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RTSP_ERROR("\n\rReceive unrecognized command!");
|
||||||
|
rtsp_cmd_error(rtsp_ctx);
|
||||||
|
ok = write(client_socket, rtsp_ctx->response, strlen(rtsp_ctx->response));
|
||||||
|
if (ok <= 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
RTSP_ERROR("\n\rsend ERROR response failed!");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
rtsp_ctx->state = RTSP_INIT;
|
||||||
|
}
|
||||||
|
if((rtsp_ctx->is_rtp_start == 0) && (rtsp_ctx->state == RTSP_PLAYING))
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
rtsp_ctx->state = RTSP_INIT;
|
||||||
|
RtlUpSema(&rtsp_ctx->start_rtp_sema);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
rtsp_ctx->state = RTSP_INIT;
|
||||||
|
close(client_socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
exit:
|
||||||
|
if((rtsp_ctx->is_rtp_start) == 1){
|
||||||
|
RtlUpSema(&rtsp_ctx->start_rtp_sema);
|
||||||
|
}
|
||||||
|
printf("\n\rrtsp -> Available heap 0x%x\n", xPortGetFreeHeapSize());
|
||||||
|
close(client_socket);
|
||||||
|
close(rtsp_ctx->connect_ctx.socket_id);
|
||||||
|
if(request_header != NULL)
|
||||||
|
free(request_header);
|
||||||
|
/*wait until rtp task being destroyed*/
|
||||||
|
while((rtsp_ctx->is_rtp_start))
|
||||||
|
{
|
||||||
|
vTaskDelay(100);
|
||||||
|
}
|
||||||
|
rtsp_context_free(rtsp_ctx);
|
||||||
|
if(rtsp_ctx != NULL)
|
||||||
|
free(rtsp_ctx);
|
||||||
|
RTSP_ERROR("\n\rkill rtsp server thread!");
|
||||||
|
//printf("Available heap 0x%x\n", xPortGetFreeHeapSize());
|
||||||
|
//thread must be killed after server socket is terminated
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uvc_rtp_udp_init(struct stream_context *stream_ctx)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct rtsp_context *rtsp_ctx = (struct rtsp_context *)stream_ctx->protoCtx;
|
||||||
|
struct uvc_buf_context buf;
|
||||||
|
struct rtp_object *payload;
|
||||||
|
struct sockaddr_in rtp_addr;
|
||||||
|
int rtp_socket;
|
||||||
|
int i, ret;
|
||||||
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||||
|
int rtp_port;
|
||||||
|
/* varibles for recording statistic use*/
|
||||||
|
unsigned int cnt, total, total_time, time1, time2, time3;
|
||||||
|
cnt = total = total_time = time1 = time2 = time3 = 0;
|
||||||
|
/*init rtp socket*/
|
||||||
|
rtp_socket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
rtp_port = rtsp_ctx->transport.serverport_min;
|
||||||
|
memset(&rtp_addr, 0, addrlen);
|
||||||
|
rtp_addr.sin_family = AF_INET;
|
||||||
|
rtp_addr.sin_addr.s_addr = *(uint32_t *)(rtsp_ctx->connect_ctx.server_ip);
|
||||||
|
rtp_addr.sin_port = htons((u16)rtp_port);
|
||||||
|
if (bind(rtp_socket,(struct sockaddr *)&rtp_addr, addrlen)<0) {
|
||||||
|
RTSP_ERROR("bind failed\r\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
restart:
|
||||||
|
while((stream_ctx->isProcess)&&(rtsp_ctx->state == RTSP_PLAYING))
|
||||||
|
{
|
||||||
|
if(RtlDownSemaWithTimeout(&payload_queue.wait_sema, 5)==0)
|
||||||
|
continue;
|
||||||
|
time1 = time3;
|
||||||
|
time2 = xTaskGetTickCount();
|
||||||
|
/*send rtp payload*/
|
||||||
|
if(!list_empty(&payload_queue.wait_queue))
|
||||||
|
{
|
||||||
|
RtlDownMutex(&payload_queue.wait_mutex);
|
||||||
|
payload = list_first_entry(&payload_queue.wait_queue, struct rtp_object, rtp_list);
|
||||||
|
if(payload == NULL)
|
||||||
|
{
|
||||||
|
RtlUpMutex(&payload_queue.wait_mutex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list_del_init(&payload->rtp_list);
|
||||||
|
RtlUpMutex(&payload_queue.wait_mutex);
|
||||||
|
|
||||||
|
if(rtsp_ctx->state == RTSP_PLAYING)
|
||||||
|
{
|
||||||
|
|
||||||
|
payload->connect_ctx.socket_id = rtp_socket;
|
||||||
|
payload->connect_ctx.port = (u16)rtsp_ctx->transport.clientport_min;
|
||||||
|
payload->connect_ctx.server_ip = rtsp_ctx->connect_ctx.server_ip;
|
||||||
|
payload->connect_ctx.remote_ip = rtsp_ctx->connect_ctx.remote_ip;
|
||||||
|
|
||||||
|
ret = rtp_udp_send(stream_ctx, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
//dequeue the this buffer from payload_queue
|
||||||
|
RtlDownMutex(&payload_queue.done_mutex);
|
||||||
|
list_add_tail(&payload->rtp_list, &payload_queue.done_queue);
|
||||||
|
RtlUpMutex(&payload_queue.done_mutex);
|
||||||
|
RtlUpSema(&payload_queue.done_sema);
|
||||||
|
|
||||||
|
time3 = xTaskGetTickCount();
|
||||||
|
cnt ++;
|
||||||
|
total += payload->len;
|
||||||
|
total_time += (time3-time1);
|
||||||
|
if(cnt == 100)
|
||||||
|
{
|
||||||
|
/* print statistics info */
|
||||||
|
/*1.average frame size(kB) T:2.time waited for next frame sending start(ms)-3.udp sending time(ms) 4.frame rate(fps)*/
|
||||||
|
printf("\n\r%dkB T:%d-%d %dfps", (total/102400), (time2 - time1), (time3 - time2), (100000/total_time));
|
||||||
|
cnt = 0;
|
||||||
|
total = 0;
|
||||||
|
total_time = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
mdelay(1000);
|
||||||
|
if(rtsp_ctx->state == RTSP_READY)
|
||||||
|
{
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
close(rtp_socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uvc_rtp_tcp_init(struct stream_context *stream_ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void uvc_rtp_multi_init(struct stream_context *stream_ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void uvc_rtp_handle(void *param)
|
||||||
|
{
|
||||||
|
struct stream_context *stream_ctx = (struct stream_context *)param;
|
||||||
|
struct rtsp_context *rtsp_ctx = (struct rtsp_context *)stream_ctx->protoCtx;
|
||||||
|
|
||||||
|
/*go down when rtsp state change to playing*/
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
RtlDownSema(&rtsp_ctx->start_rtp_sema);
|
||||||
|
/*check rtp cast mode*/
|
||||||
|
if(rtsp_ctx->state == RTSP_PLAYING)
|
||||||
|
{
|
||||||
|
printf("\n\rrtp start...");
|
||||||
|
switch(rtsp_ctx->transport.castMode)
|
||||||
|
{
|
||||||
|
case(UNICAST_UDP_MODE):
|
||||||
|
uvc_rtp_udp_init(stream_ctx);
|
||||||
|
break;
|
||||||
|
case(MULTICAST_MODE):
|
||||||
|
uvc_rtp_tcp_init(stream_ctx);
|
||||||
|
break;
|
||||||
|
case(UNICAST_TCP_MODE):
|
||||||
|
uvc_rtp_multi_init(stream_ctx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RTSP_ERROR("\r\n unknown streaming mode! Go back to RTSP_INIT state\n");
|
||||||
|
rtsp_ctx->is_rtp_start = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("\n\rrtp stop...");
|
||||||
|
}
|
||||||
|
rtsp_ctx->is_rtp_start = 0;
|
||||||
|
RTSP_ERROR("\n\rkill rtp server thread!");
|
||||||
|
//printf("Available heap 0x%x\n", xPortGetFreeHeapSize());
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uvc_rtp_init(struct rtsp_context *rtsp_ctx)
|
||||||
|
{
|
||||||
|
struct stream_context *stream_ctx = (struct stream_context *)rtsp_ctx->stream_ctx;
|
||||||
|
|
||||||
|
if(xTaskCreate(uvc_rtp_handle, ((const signed char*)"uvc_rtp_handle"), 2048, (void *)stream_ctx, tskIDLE_PRIORITY + 2, NULL) != pdPASS) {
|
||||||
|
RTSP_ERROR("\r\n uvc_rtp_handle: Create Task Error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uvc_task_init(void * param)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*entry to start uvc streaming -- dequeue uvc buffer*/
|
||||||
|
if(xTaskCreate(uvc_entry_handle, ((const signed char*)"uvc_entry_handle"), 1024, param, tskIDLE_PRIORITY + 2, NULL) != pdPASS) {
|
||||||
|
UVC_ERROR("\r\n uvc_entry_handle: Create Task Error\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*entry to start rtsp server*/
|
||||||
|
#if UVC_RTSP_EN
|
||||||
|
if(xTaskCreate(uvc_rtsp_handle, ((const signed char*)"uvc_rtsp_handle"), 4096, param, tskIDLE_PRIORITY + 2, NULL) != pdPASS) {
|
||||||
|
RTSP_ERROR("\r\n uvc_rtsp_handle: Create Task Error\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************end of rtsp/rtp with motion-jpeg************************************************/
|
25
RTL00_SDKV35a/component/common/example/uvc/example_uvc.h
Normal file
25
RTL00_SDKV35a/component/common/example/uvc/example_uvc.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef EXAMPLE_UVC_H
|
||||||
|
#define EXAMPLE_UVC_H
|
||||||
|
|
||||||
|
#include <platform/platform_stdlib.h>
|
||||||
|
#include "platform_opts.h"
|
||||||
|
#include "dlist.h"
|
||||||
|
#include "osdep_api.h"
|
||||||
|
|
||||||
|
#define UVC_RTSP_EN 1
|
||||||
|
|
||||||
|
//example structure to handle rtp_object operation in queue
|
||||||
|
struct rtp_payload_queue
|
||||||
|
{
|
||||||
|
struct list_head wait_queue;
|
||||||
|
_Mutex wait_mutex;
|
||||||
|
struct list_head done_queue;
|
||||||
|
_Mutex done_mutex;
|
||||||
|
_Sema wait_sema; //up it whenever a rtp payload queue in wait_queue
|
||||||
|
_Sema done_sema; //up it whenever a rtp payload queue in done_queue
|
||||||
|
int flush_err;
|
||||||
|
};
|
||||||
|
|
||||||
|
void example_uvc(void);
|
||||||
|
|
||||||
|
#endif /* EXAMPLE_UVC_H */
|
8
RTL00_SDKV35a/component/common/example/uvc/readme.txt
Normal file
8
RTL00_SDKV35a/component/common/example/uvc/readme.txt
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
THis is an example for USB Video Capture specifically for motion-jpeg capturing.
|
||||||
|
|
||||||
|
Please MAKE SURE to reserve enough heap size for UVC by raising configTOTAL_HEAP_SIZE in freeRTOSconfig.h & turning off some functions (e.g. WPS, JDSMART, ATcmd for internal and system) since image frame storing could consume quite large memory space.
|
||||||
|
|
||||||
|
TO switch on UVC example, make sure CONFIG_USB_EN is enabled (in platform_autoconf.h) & set CONFIG_EXAMPLE_UVC to 1 (in platform_opts.h).
|
||||||
|
|
||||||
|
TO combine uvc with rtsp server, make sure wlan module is enabled & set UVC_WLAN_TRANSFER to 1 (in example_uvc.h).
|
File diff suppressed because it is too large
Load diff
111
RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/rtl8195a_usb.h
Normal file
111
RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/rtl8195a_usb.h
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Routines to access hardware
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Realtek Semiconductor Corp.
|
||||||
|
*
|
||||||
|
* This module is a confidential and proprietary property of RealTek and
|
||||||
|
* possession or use of this module requires written permission of RealTek.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _RTL8195A_USB_H_
|
||||||
|
#define _RTL8195A_USB_H_
|
||||||
|
|
||||||
|
|
||||||
|
// common command for USB
|
||||||
|
#define USB_CMD_TX_ETH 0x83 // request to TX a 802.3 packet
|
||||||
|
#define USB_CMD_TX_WLN 0x81 // request to TX a 802.11 packet
|
||||||
|
#define USB_CMD_H2C 0x11 // H2C(host to device) command packet
|
||||||
|
#define USB_CMD_MEMRD 0x51 // request to read a block of memory data
|
||||||
|
#define USB_CMD_MEMWR 0x53 // request to write a block of memory
|
||||||
|
#define USB_CMD_MEMST 0x55 // request to set a block of memory with a value
|
||||||
|
#define USB_CMD_STARTUP 0x61 // request to jump to the start up function
|
||||||
|
|
||||||
|
#define USB_CMD_RX_ETH 0x82 // indicate a RX 802.3 packet
|
||||||
|
#define USB_CMD_RX_WLN 0x80 // indicate a RX 802.11 packet
|
||||||
|
#define USB_CMD_C2H 0x10 // C2H(device to host) command packet
|
||||||
|
#define USB_CMD_MEMRD_RSP 0x50 // response to memory block read command
|
||||||
|
#define USB_CMD_MEMWR_RSP 0x52 // response to memory write command
|
||||||
|
#define USB_CMD_MEMST_RSP 0x54 // response to memory set command
|
||||||
|
#define USB_CMD_STARTED 0x60 // indicate the program has jumped to the given function
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: This data structer just for test, we should modify it for the normal driver
|
||||||
|
typedef struct _USB_TX_DESC{
|
||||||
|
// u4Byte 0
|
||||||
|
#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN)
|
||||||
|
u32 txpktsize:16; // bit[15:0]
|
||||||
|
u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC)
|
||||||
|
u32 bus_agg_num:8; // bit[31:24], the bus aggregation number
|
||||||
|
#else
|
||||||
|
u32 bus_agg_num:8; // bit[31:24], the bus aggregation number
|
||||||
|
u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC)
|
||||||
|
u32 txpktsize:16; // bit[15:0]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// u4Byte 1
|
||||||
|
#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN)
|
||||||
|
u32 type:8; // bit[7:0], the packet type
|
||||||
|
u32 rsvd0:24;
|
||||||
|
#else
|
||||||
|
u32 rsvd0:24;
|
||||||
|
u32 type:8; // bit[7:0], the packet type
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// u4Byte 2
|
||||||
|
u32 rsvd1;
|
||||||
|
|
||||||
|
// u4Byte 3
|
||||||
|
u32 rsvd2;
|
||||||
|
|
||||||
|
// u4Byte 4
|
||||||
|
u32 rsvd3;
|
||||||
|
|
||||||
|
// u4Byte 5
|
||||||
|
u32 rsvd4;
|
||||||
|
} USB_TX_DESC, *PUSB_TX_DESC;
|
||||||
|
|
||||||
|
#define SIZE_USB_TX_DESC sizeof(USB_TX_DESC)
|
||||||
|
|
||||||
|
// TODO: This data structer just for test, we should modify it for the normal driver
|
||||||
|
typedef struct _USB_RX_DESC{
|
||||||
|
// u4Byte 0
|
||||||
|
#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN)
|
||||||
|
u32 pkt_len:16; // bit[15:0], the packet size
|
||||||
|
u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc
|
||||||
|
u32 rsvd0:6; // bit[29:24]
|
||||||
|
u32 icv:1; // bit[30], ICV error
|
||||||
|
u32 crc:1; // bit[31], CRC error
|
||||||
|
#else
|
||||||
|
u32 crc:1; // bit[31], CRC error
|
||||||
|
u32 icv:1; // bit[30], ICV error
|
||||||
|
u32 rsvd0:6; // bit[29:24]
|
||||||
|
u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc
|
||||||
|
u32 pkt_len:16; // bit[15:0], the packet size
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// u4Byte 1
|
||||||
|
#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN)
|
||||||
|
u32 type:8; // bit[7:0], the type of this packet
|
||||||
|
u32 rsvd1:24; // bit[31:8]
|
||||||
|
#else
|
||||||
|
u32 rsvd1:24; // bit[31:8]
|
||||||
|
u32 type:8; // bit[7:0], the type of this packet
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// u4Byte 2
|
||||||
|
u32 rsvd2;
|
||||||
|
|
||||||
|
// u4Byte 3
|
||||||
|
u32 rsvd3;
|
||||||
|
|
||||||
|
// u4Byte 4
|
||||||
|
u32 rsvd4;
|
||||||
|
|
||||||
|
// u4Byte 5
|
||||||
|
u32 rsvd5;
|
||||||
|
} USB_RX_DESC, *PUSB_RX_DESC;
|
||||||
|
|
||||||
|
#define SIZE_USB_RX_DESC sizeof(USB_RX_DESC)
|
||||||
|
|
||||||
|
#endif // #ifndef _RTL8195A_USB_H_
|
||||||
|
|
|
@ -4,4 +4,4 @@ hal_misc.c +
|
||||||
hal_pinmux.c +
|
hal_pinmux.c +
|
||||||
hal_sdio_host.c +
|
hal_sdio_host.c +
|
||||||
hal_soc_ps_monitor.c +
|
hal_soc_ps_monitor.c +
|
||||||
hal_spi_flash_ram.c +-
|
hal_spi_flash_ram.c +
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue