initial commit

This commit is contained in:
2024-12-15 00:34:01 +06:00
commit 31efbc726f
1576 changed files with 657692 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
#ifndef _EXCHBUF_H
#define _EXCHBUF_H
#include "cmsis_os.h"
/*service task state*/
#define S_STOP 0x00
#define S_RUN 0x01
#define S_FROZEN 0X02
#define CMD_SET_HEIGHT 0x00
#define CMD_SET_WIDTH 0x01
#define CMD_SET_BITRATE 0x02
#define CMD_SET_FRAMERATE 0x03
#define CMD_SET_CPZRATIO 0x04
#define CMD_SET_FRAMETYPE 0x05
#define CMD_SET_SAMPLERATE 0x06
#define CMD_SET_CHANNEL 0x07
#define CMD_SET_CODEC 0x08
#define CMD_SET_STREAMNUM 0x09
#define CMD_SET_SPS 0x0a
#define CMD_SET_PPS 0x0b
#define CMD_SET_LEVEL 0x0c
#define CMD_SET_APPLY 0x1f
#define CMD_SET_STREAMMING 0x20
#define CMD_SET_INPUT_QUEUE 0x21
#define CMD_SET_OUTPUT_QUEUE 0x22
#define CMD_SET_PRIV_BUF 0x23
#define CMD_SET_TASK_ON 0x24
#define CMD_SET_TASK_FROZEN 0x25
#define CMD_SET_TASK_OFF 0x26
#define CMD_SELECT_CHANNEL 0x30
#define CMD_ENABLE_CHANNEL 0X31
#define CMD_DISABLE_CHANNEL 0x32
#define CMD_SET_CB_START 0x40
#define CMD_SET_CB_STOP 0x41
#define CMD_SET_CB_PAUSE 0x42
#define CMD_SET_CB_CUSTOMCMD 0x43
#define CMD_FLUSH 0x50
#define CMD_SET_FLAG 0X51
#define CMD_GET_STREAM_READY 0x52
#define CMD_GET_STREAM_STATUS 0x53
#define STAT_INIT 0
#define STAT_USED 1
#define STAT_READY 2
#define STAT_RESERVED 3
#define TIME_SYNC_EN 0
#define TIME_SYNC_DIS 1
#define FMT_V_MJPG 0x00
#define FMT_V_H264 0x01
#define FMT_V_MP4V_ES 0x02
#define FMT_A_PCMU 0x10
#define FMT_A_PCMA 0x11
#define FMT_A_MP4A_LATM 0x12
#define FMT_AV_UNKNOWN 0xFF
/*mp4 storage*/
#define CMD_SET_ST_PERIOD 0X60
#define CMD_SET_ST_TOTAL 0X61
#define CMD_SET_ST_TYPE 0X62
#define CMD_SET_ST_FILENAME 0x63
#define CMD_SET_ST_START 0x64
/*mp4 storage*/
#define STORAGE_ALL 0
#define STORAGE_VIDEO 1
#define STORAGE_AUDIO 2
#define MFT_CMD 0
#define MFT_DATA 1
typedef struct _exch_buf{
//_list node; // linking node
uint32_t type; // CMD, or DATA
uint32_t cmd; // command
uint32_t arg; // command arg
uint8_t* data; //
uint32_t index;
uint32_t len;
uint32_t timestamp; // 0: not set
uint32_t codec_fmt; // FMT_V_xx or FMT_A_xx
uint32_t state;
void* priv; // private use
}exch_buf_t;
typedef int (*mmf_cb_t)(void*);
/* common error code for MMF */
#define EAGAIN 11
#define EFAULT 14
#define EINVAL 22
#ifndef ON
#define ON 1
#endif
#ifndef OFF
#define OFF 0
#endif
#ifndef ENABLE
#define ENABLE 1
#endif
#ifndef DISABLE
#define DISABLE 0
#endif
#endif

View File

@@ -0,0 +1,30 @@
#ifndef _STREAM_H
#define _STREAM_H
#include "cmsis_os.h"
#include "mmf_common.h"
typedef struct _media_sink_module{
void* (*create)(void);
void (*destroy)(void*);
int (*set_param)(void*, int, int);
int (*handle)(void*, void*);
}msink_module_t;
typedef struct _media_sink_context{
xQueueHandle input_qid;
xQueueHandle output_qid;
int state;
xTaskHandle hdl_task;
void* drv_priv; // private data for module
msink_module_t *sink;
}msink_context;
void mmf_sink_close(msink_context* ctx);
msink_context* mmf_sink_open(msink_module_t *sink);
int mmf_sink_ctrl(msink_context* ctx, int cmd, int arg);
int mmf_sink_put_frame(msink_context* ctx, exch_buf_t* exbuf);
// must be here
#include "mmf_sink_modules/mmf_sink_list.h"
#endif

View File

@@ -0,0 +1,137 @@
#include "mmf_sink.h"
#include "i2s_api.h"
#include "g711/g711_codec.h"
#define BUF_BLK 3 //MUST BE GREATER OR EQUAL TO 2
static u8 i2s_dec_buf[320]; //store decoded data
static u8 i2s_chl_buf[640*(BUF_BLK+1)]; //store mono2stereo data
#define I2S_DMA_PAGE_NUM 2
#define I2S_DMA_PAGE_SIZE (640)
static u8 i2s_tx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM];
static u8 i2s_rx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM];
#define I2S_SCLK_PIN PC_1
#define I2S_WS_PIN PC_0
#define I2S_SD_PIN PC_2
static u32 update_flag = 0;
static u32 update_token = 0;
static u32 prev_token = 0;
u8 *play_ptr = i2s_chl_buf;
static void i2s_tx_complete(void *data, char* pbuf){
i2s_t *obj = (i2s_t *)data;
int *ptx_buf;
ptx_buf = i2s_get_tx_page(obj);
if(update_token > prev_token)
update_flag = 1;
else
update_flag = 0;
if(update_flag)
{
_memcpy((void*)ptx_buf, (void*)play_ptr, I2S_DMA_PAGE_SIZE);
play_ptr += I2S_DMA_PAGE_SIZE;
if(play_ptr >= i2s_chl_buf + BUF_BLK*I2S_DMA_PAGE_SIZE)
{
play_ptr = i2s_chl_buf;
}
update_token--;
}
else
_memset((void*)ptx_buf, 0, I2S_DMA_PAGE_SIZE);
i2s_send_page(obj, (uint32_t*)ptx_buf);
//printf("\n\r%d", update_token);
}
static void i2s_rx_complete(void *data, char* pbuf){
return;
}
void i2s_sink_mod_close(void* ctx)
{
i2s_t* i2s_obj = (i2s_t*) ctx;
i2s_deinit(i2s_obj);
free(i2s_obj);
}
void* i2s_sink_mod_open(void)
{
i2s_t* i2s_obj = malloc(sizeof(i2s_t));
if(i2s_obj == NULL)
return NULL;
alc5651_init();
alc5651_init_interface2(); // connect to ALC interface 2
//default setting i2s obj
i2s_obj->channel_num = /*CH_MONO*/CH_STEREO;
i2s_obj->sampling_rate = I2S_SR_8KHZ;
i2s_obj->word_length = WL_16b;
i2s_obj->direction = I2S_DIR_TX;
i2s_init(i2s_obj, I2S_SCLK_PIN, I2S_WS_PIN, I2S_SD_PIN);
i2s_set_dma_buffer(i2s_obj, (char*)i2s_tx_buf, (char*)i2s_rx_buf, \
I2S_DMA_PAGE_NUM, I2S_DMA_PAGE_SIZE);
i2s_tx_irq_handler(i2s_obj, (i2s_irq_handler)i2s_tx_complete, (uint32_t)i2s_obj);
i2s_rx_irq_handler(i2s_obj, (i2s_irq_handler)i2s_rx_complete, (uint32_t)i2s_obj);
return i2s_obj;
}
int i2s_sink_mod_set_param(void* ctx, int cmd, int arg)
{
i2s_t* i2s_obj = (i2s_t*) ctx;
switch(cmd){
case CMD_SET_STREAMMING:
if(arg == ON){
i2s_send_page(i2s_obj, (uint32_t*)i2s_get_tx_page(i2s_obj));
}else{
}
break;
default:
break;
}
return 0;
}
//send audio data here
static int cache_byte = 0;
u8 *cache_ptr = i2s_chl_buf;
int i2s_sink_mod_handle(void* ctx, void* b)
{
i2s_t* i2s_obj = (i2s_t*) ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
if(exbuf->state != STAT_READY)
return -EAGAIN;
G711_decoder(exbuf->data, (short*)i2s_dec_buf, I2S_MODE_G711U, exbuf->len);
//mono2stereo(i2s_dec_buf, i2s_chl_buf, 320, 16);
mono2stereo(i2s_dec_buf, cache_ptr, exbuf->len*2, 16);
cache_byte += exbuf->len*4;
cache_ptr += exbuf->len*4;
if(cache_ptr >= i2s_chl_buf + BUF_BLK*I2S_DMA_PAGE_SIZE)
{
memcpy(i2s_chl_buf, i2s_chl_buf + BUF_BLK*I2S_DMA_PAGE_SIZE, cache_ptr - (i2s_chl_buf + BUF_BLK*I2S_DMA_PAGE_SIZE));
cache_ptr -= BUF_BLK*I2S_DMA_PAGE_SIZE;
}
if(cache_byte >= I2S_DMA_PAGE_SIZE)
{
cache_byte %= I2S_DMA_PAGE_SIZE;
//printf("\n\rcache:%dB", cache_byte);
update_token++;
}
//printf("\n\r%d", update_token);
while(update_token >= prev_token + BUF_BLK - 1)//MINUS 1 TO AVOID RING BUFFER OUT RACE
vTaskDelay(1);
exbuf->state = STAT_USED;
return 0;
}
msink_module_t i2s_sink_module =
{
.create = i2s_sink_mod_open,
.destroy = i2s_sink_mod_close,
.set_param = i2s_sink_mod_set_param,
.handle = i2s_sink_mod_handle,
};

View File

@@ -0,0 +1,10 @@
#ifndef _STREAM_MODULES_H
#define _STREAM_MODULES_H
#include "../mmf_sink.h"
//list all avaliable modules here
extern msink_module_t rtsp_module;
extern msink_module_t rtsp2_module;
extern msink_module_t i2s_sink_module;
extern msink_module_t mp3_sink_module;
#endif

View File

@@ -0,0 +1,109 @@
#include "mmf_sink_mp3.h"
/*SDRAM_DATA_SECTION*/ //unsigned char MP3_ip[640];
signed short WAV_op[4608];
#define I2S_DMA_PAGE_SIZE 4608 // 2 ~ 4096
#define I2S_DMA_PAGE_NUM 2 // Vaild number is 2~4
static u8 i2s_tx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM];
static u8 i2s_rx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM];
#define I2S_SCLK_PIN PC_1
#define I2S_WS_PIN PC_0
#define I2S_SD_PIN PC_2
static i2s_t i2s_obj;
mp3_decoder_t mp3;
mp3_info_t info;
int frame_size = 0;
int *ptx_buf;
static void i2s_tx_complete(void *data, char *pbuf)
{
//
}
static void i2s_rx_complete(void *data, char* pbuf)
{
//
}
void cleanup()
{
mp3_done(mp3);
}
void mp3_sink_mod_close(void* ctx)
{
cleanup();
}
void* mp3_sink_mod_open(void)
{
i2s_obj.channel_num = CH_STEREO;
i2s_obj.sampling_rate = I2S_SR_44p1KHZ;
i2s_obj.word_length = WL_16b;
i2s_obj.direction = I2S_DIR_TXRX;
i2s_init(&i2s_obj, I2S_SCLK_PIN, I2S_WS_PIN, I2S_SD_PIN);
i2s_set_dma_buffer(&i2s_obj, (char*)i2s_tx_buf, (char*)i2s_rx_buf, \
I2S_DMA_PAGE_NUM, I2S_DMA_PAGE_SIZE);
i2s_tx_irq_handler(&i2s_obj, (i2s_irq_handler)i2s_tx_complete, (uint32_t)&i2s_obj);
i2s_rx_irq_handler(&i2s_obj, (i2s_irq_handler)i2s_rx_complete, (uint32_t)&i2s_obj);
mp3 = mp3_create();
if(!mp3)
{
printf("mp3 context create fail\n");
cleanup();
}
#if CONFIG_EXAMPLE_MP3_STREAM_SGTL5000
sgtl5000_enable();
sgtl5000_setVolume(0.5);
#else
alc5651_init();
alc5651_init_interface2();
#endif
return (void*)1;
}
int mp3_sink_mod_set_param(void* ctx, int cmd, int arg)
{
return 1;
}
int mp3_sink_mod_handle(void* ctx, void* b)
{
exch_buf_t *exbuf = (exch_buf_t*)b;
if(exbuf->state != STAT_READY)
return -EAGAIN;
/* Read a block */
frame_size = mp3_decode(mp3, (exbuf->data), (exbuf->len), WAV_op, &info);
retry:
ptx_buf = i2s_get_tx_page(&i2s_obj);
if(ptx_buf){
if((frame_size>0)&&(info.audio_bytes>0))
{
memcpy((void*)ptx_buf, (void*)WAV_op, info.audio_bytes);
i2s_send_page(&i2s_obj, (uint32_t*)ptx_buf);
}
}else{
vTaskDelay(1);
goto retry;
}
exbuf->state = STAT_USED;
return 1;
}
msink_module_t mp3_sink_module =
{
.create = mp3_sink_mod_open,
.destroy = mp3_sink_mod_close,
.set_param = mp3_sink_mod_set_param,
.handle = mp3_sink_mod_handle,
};

View File

@@ -0,0 +1,19 @@
#ifndef MMF_SINK_MP3_FILE_H
#define MMF_SINK_MP3_FILE_H
#include "mmf_sink.h"
#include "FreeRTOS.h"
#include "task.h"
#include "platform_opts.h"
#include "mp3/mp3_codec.h"
#include "diag.h"
#include "i2s_api.h"
#include "analogin_api.h"
#include <stdlib.h>
#include "section_config.h"
#if CONFIG_EXAMPLE_MP3_STREAM_SGTL5000
#include "sgtl5000.h"
#else
#include "alc5651.h"
#endif
#endif /* MMF_SINK_MP3_FILE_H */

View File

@@ -0,0 +1,210 @@
#include "ff.h"
#include <fatfs_ext/inc/ff_driver.h>
#include <platform/platform_stdlib.h>
#include "basic_types.h"
#include "section_config.h"
#include "sdio_host.h"
#include <disk_if/inc/sdcard.h>
#include "FreeRTOS.h"
#include "task.h"
#include <platform/platform_stdlib.h>
#include "basic_types.h"
#include "platform_opts.h"
#include "mmf_sink.h"
#include "sockets.h"
#include "lwip/netif.h"
#include "mp4_encap.h"
#define AUDIO_SIZE 1024*10
#define VIDEO_SIZE 1024*10
#define MOOV_BOX_SIZE 1024*64
#define H264_BUF_SIZE 1024*224//must 32 kb multiple
SDRAM_DATA_SECTION unsigned char moov_box_[MOOV_BOX_SIZE];
SDRAM_DATA_SECTION int video_buffer_index[VIDEO_SIZE];
SDRAM_DATA_SECTION int video_buffer_size[VIDEO_SIZE];
SDRAM_DATA_SECTION int audio_buffer_index[AUDIO_SIZE];
SDRAM_DATA_SECTION int audio_buffer_size[AUDIO_SIZE];
SDRAM_DATA_SECTION unsigned char h264_buffer[H264_BUF_SIZE];
int fatfs_init(void* ctx){
char path[64];
int test_result = 1;
int ret = 0;
pmp4_context mp4_ctx = (pmp4_context)ctx;
//1 init disk drive
DBG_8195A("Init Disk driver.\n");
// Set sdio debug level
DBG_INFO_MSG_OFF(_DBG_SDIO_);
DBG_WARN_MSG_OFF(_DBG_SDIO_);
DBG_ERR_MSG_ON(_DBG_SDIO_);
if(sdio_init_host()!=0){
DBG_8195A("SDIO host init fail.\n");
return -1;
}
//1 register disk driver to fatfs
DBG_8195A("Register disk driver to Fatfs.\n");
mp4_ctx->drv_num = FATFS_RegisterDiskDriver(&SD_disk_Driver);
if(mp4_ctx->drv_num < 0){
DBG_8195A("Rigester disk driver to FATFS fail.\n");
goto fail;
}else{
mp4_ctx->_drv[0] = mp4_ctx->drv_num + '0';
mp4_ctx->_drv[1] = ':';
mp4_ctx->_drv[2] = '/';
mp4_ctx->_drv[3] = 0;
}
DBG_8195A("FatFS Write begin......\n\n");
printf("\r\ndrv(%s)", mp4_ctx->_drv);
if(f_mount(&mp4_ctx->m_fs,mp4_ctx->_drv, 1)!= FR_OK){
DBG_8195A("FATFS mount logical drive fail.\n");
goto fail;
}
return 0;
fail:
sdio_deinit_host();
return -1;
}
int fatfs_close(void *ctx){
pmp4_context mp4_ctx = (pmp4_context)ctx;
if(f_mount(NULL,mp4_ctx->_drv, 1) != FR_OK){
DBG_8195A("FATFS unmount logical drive fail.\n");
}
if(FATFS_UnRegisterDiskDriver(mp4_ctx->drv_num))
DBG_8195A("Unregister disk driver from FATFS fail.\n");
sdio_deinit_host();
return 0;
}
void mp4_mod_close(void* ctx)
{
pmp4_context mp4_ctx = (pmp4_context)ctx;
mp4_muxer_close(mp4_ctx);
fatfs_close(mp4_ctx);
free(mp4_ctx);
}
void* mp4_mod_open(void)
{
pmp4_context mp4_ctx = (pmp4_context)malloc(sizeof(mp4_context));
if(!mp4_ctx){
printf("malloc failed\r\n");
return NULL;
}
memset(mp4_ctx,0,sizeof(mp4_context));
mp4_muxer_init(mp4_ctx);
if(fatfs_init(mp4_ctx)<0){
free(mp4_ctx);
return NULL;
}
set_mp4_audio_buffer(mp4_ctx,audio_buffer_index,audio_buffer_size,AUDIO_SIZE);
set_mp4_video_buffer(mp4_ctx,video_buffer_index,video_buffer_size,VIDEO_SIZE);
set_mp4_moov_buffer(mp4_ctx,moov_box_,MOOV_BOX_SIZE);
set_mp4_write_buffer(mp4_ctx,h264_buffer,H264_BUF_SIZE);
printf("mp4_mod_open\r\n");
return (void*)mp4_ctx;
}
int mp4_mod_set_param(void* ctx, int cmd, int arg)
{
int ret = 0;
pmp4_context mp4_ctx = (pmp4_context)ctx;
switch(cmd){
case CMD_SET_HEIGHT:
mp4_ctx->height=arg;
break;
case CMD_SET_WIDTH:
mp4_ctx->width = arg;
break;
case CMD_SET_FRAMERATE:
mp4_ctx->frame_rate = arg;
break;
case CMD_SET_CHANNEL:
mp4_ctx->channel_count = arg;
break;
case CMD_SET_SAMPLERATE:
mp4_ctx->sample_rate = arg;
break;
case CMD_SET_ST_PERIOD:
mp4_ctx->period_time = arg*1000;
break;
case CMD_SET_ST_TOTAL:
mp4_ctx->file_total = arg;
break;
case CMD_SET_ST_TYPE:
mp4_ctx->type = arg;
break;
case CMD_SET_ST_FILENAME:
memset(mp4_ctx->filename,0,sizeof(mp4_ctx->filename));
strcpy(mp4_ctx->filename,(char*)arg);
break;
case CMD_SET_ST_START:
mp4_set_start_status(mp4_ctx);
break;
default:
ret = EINVAL;
break;
}
return ret;
}
#if 0
int mp4_mod_handle(void* ctx, void* b)
{
pmp4_context mp4_ctx = (pmp4_context)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
int status = 0;
if((exbuf->state == STAT_INIT) || (exbuf->state == STAT_USED))
return -EAGAIN;
if(exbuf->codec_fmt == FMT_A_MP4A_LATM || exbuf->codec_fmt == FMT_V_MP4V_ES){
mp4_handle(mp4_ctx,exbuf->data,exbuf->len,exbuf->codec_fmt);
}
exbuf->state=STAT_USED;
return 0;
}
#endif
int mp4_mod_handle(void* ctx, void* b)
{
pmp4_context mp4_ctx = (pmp4_context)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
int status = 0;
if((exbuf->state == STAT_INIT) || (exbuf->state == STAT_USED))
return -EAGAIN;
if(exbuf->state == STAT_RESERVED){
if(mp4_ctx->buffer_write_status == 0)
exbuf->state=STAT_USED;
return 0;
}
if(exbuf->codec_fmt == FMT_A_MP4A_LATM || exbuf->codec_fmt == FMT_V_MP4V_ES){
mp4_handle(mp4_ctx,exbuf->data,exbuf->len,exbuf->codec_fmt);
}
if((mp4_ctx->buffer_write_status == 1) && (mp4_ctx->iframe == 1) && (exbuf->codec_fmt == FMT_V_MP4V_ES))
exbuf->state=STAT_RESERVED;
else
exbuf->state=STAT_USED;
return 0;
}
msink_module_t mp4_module =
{
.create = mp4_mod_open,
.destroy = mp4_mod_close,
.set_param = mp4_mod_set_param,
.handle = mp4_mod_handle,
};

View File

@@ -0,0 +1,215 @@
#include "mmf_sink.h"
//rtsp header files
#include "rtsp/rtsp_api.h"
#include "sockets.h"
#include "lwip/netif.h"
static struct rtp_object rtp_payload;
// to get stream id,
// need mutex to protect this routine? i dont think it is necessary
#define STREAM_FLOW_ID_BASE 0
static u32 stream_flow_id_bitmap = 0;
static _mutex stream_flow_id_bitmap_lock = NULL;
//static u32 rtsp_tick_offset = 0;
//static u32 rtsp_stream_num = 0;
// codec map
//
static int codec_map_v[] = {AV_CODEC_ID_MJPEG, AV_CODEC_ID_H264, AV_CODEC_ID_MP4V_ES};
static int codec_map_a[] = {AV_CODEC_ID_PCMU, AV_CODEC_ID_PCMA, AV_CODEC_ID_MP4A_LATM};
void rtsp_mod_close(void* ctx)
{
struct rtsp_context * rtsp_ctx = (struct rtsp_context *)ctx;
if(rtsp_ctx->stream_ctx[0].codec)
free(rtsp_ctx->stream_ctx[0].codec);
rtsp_close(rtsp_ctx);
rtsp_context_free(rtsp_ctx);
if(stream_flow_id_bitmap_lock != NULL)
rtw_mutex_free(&stream_flow_id_bitmap_lock);
stream_flow_id_bitmap = 0;
}
void* rtsp_mod_open(void)
{
int timeout = 10;
struct rtsp_context *rtsp_ctx = rtsp_context_create(1);
if(!rtsp_ctx) return NULL;
/*open rtsp service task*/
if(rtsp_open(rtsp_ctx)<0){
rtsp_context_free(rtsp_ctx);
rtsp_ctx = NULL;
}
while(!rtsp_is_service_enabled(rtsp_ctx)){
rtw_mdelay_os(1000);
if(timeout--<=0){
printf("\n\rwait rtsp service time out...");
goto rtsp_mod_open_fail;
}
}
// init payload object
rtp_object_init(&rtp_payload);
rtsp_ctx->stream_ctx[0].codec = malloc(sizeof(struct codec_info));
if(!rtsp_ctx->stream_ctx[0].codec)
goto rtsp_mod_open_fail;
//rtsp_clock_init(rtsp_ctx->stream_ctx[0].codec->clock_rate);
//rtsp_tick_offset = rtw_get_current_time();
//rtsp_stream_num = 1;
return (void*)rtsp_ctx;
rtsp_mod_open_fail:
rtp_object_deinit(&rtp_payload);
rtsp_mod_close(rtsp_ctx);
return NULL;
}
int rtsp_mod_set_param(void* ctx, int cmd, int arg)
{
struct rtsp_context *rtsp_ctx = (struct rtsp_context *)ctx;
struct stream_context *stream_ctx = &rtsp_ctx->stream_ctx[0];
int *codec_map = NULL;
switch(cmd){
case CMD_SET_FRAMERATE:
stream_ctx->framerate = arg;
break;
case CMD_SET_BITRATE:
stream_ctx->bitrate = arg;
break;
case CMD_SET_SAMPLERATE:
stream_ctx->samplerate = arg;
break;
case CMD_SET_CHANNEL:
stream_ctx->channel = arg;
break;
// for H264
case CMD_SET_SPS:
set_sps_string((char*)arg);
break;
case CMD_SET_PPS:
set_pps_string((char*)arg);
break;
case CMD_SET_LEVEL:
set_profile_lv_string((char*)arg);
break;
case CMD_SET_APPLY:
if(stream_flow_id_bitmap_lock == NULL)
rtw_mutex_init(&stream_flow_id_bitmap_lock);
if(stream_ctx->stream_id < 0)
stream_ctx->stream_id = rtsp_get_number(STREAM_FLOW_ID_BASE, &stream_flow_id_bitmap, &stream_flow_id_bitmap_lock);
rtp_stream_statistics_sync(stream_ctx);
break;
/*
case CMD_SET_STREAMNUM:
if(arg>1){ // arg = 1, do nothing, because has been created when open
// free original stream
free(stream_ctx);
// malloc new steram and init
rtsp_ctx->nb_streams = arg;
rtsp_ctx->stream_ctx = malloc(arg * sizeof(struct stream_context));
if(!rtsp_ctx->stream_ctx) return -ENOMEM;
for(int i = 0; i < arg; i++)
{
rtsp_ctx->rtpseq[i] = 0;
rtsp_stream_context_init(rtsp_ctx, &rtsp_ctx->stream_ctx[i]);
}
}
break;
*/
case CMD_SET_STREAMMING:
if(arg == ON){
rtsp_clock_init(rtsp_ctx->stream_ctx[0].codec->clock_rate);
rtsp_start(rtsp_ctx);
// insert to input queue
rtp_object_in_stream_queue(&rtp_payload, &rtsp_ctx->stream_ctx[0]);
}else
rtsp_stop(rtsp_ctx);
break;
case CMD_SET_CODEC:
codec_map = ((arg&0xf0)==0x00)?codec_map_v:codec_map_a;
get_codec_by_id(stream_ctx->codec, codec_map[arg&0xf]);
stream_ctx->media_type = rtsp_parse_stream_media_type(stream_ctx->codec);
rtp_load_o_handler_by_codec_id(&rtp_payload, codec_map[arg&0xf]);
if(rtp_payload.rtp_object_handler == NULL)
return -EINVAL;
break;
default:
break;
}
return 0;
}
// private function
int rtsp_mod_wait_complete(void)
{
return 1;
}
// private function
int rtsp_mod_compelete_cb(void)
{
return 1;
}
int rtsp_mod_handle(void* ctx, void* b)
{
struct rtsp_context *rtsp_ctx = (struct rtsp_context *)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
struct stream_context *stream_ctx = &rtsp_ctx->stream_ctx[0];
struct rtp_object *payload = NULL;//&rtp_payload;
if(exbuf->state != STAT_READY)
return -EAGAIN;
if(rtsp_ctx->state != RTSP_PLAYING)
goto end;
// wait output not empty and get one
// Get payload from rtsp module
do{
payload = rtp_object_out_stream_queue(stream_ctx);
if(payload==NULL) vTaskDelay(1);
}while(payload == NULL);
// insert payload to rtsp_ctx stream
//printf("%d\n\r", xTaskGetTickCount());
/*fill payload*/
payload->index = exbuf->index;
payload->data = exbuf->data;
payload->len = exbuf->len;
payload->timestamp = exbuf->timestamp;
if(payload->timestamp==0)
payload->timestamp = rtsp_get_current_tick();
else
payload->timestamp = exbuf->timestamp;
//printf("ts: %8x\n\r", payload->timestamp);
/* because we will fill&send a complete frame in single rtp object, set both fs & fe to 1 and fd to 0*/
rtp_object_set_fs(payload, 1);
rtp_object_set_fe(payload, 1);
rtp_object_set_fd(payload, 0);
/* set payload state to READY to enable rtp task process this rtp object;*/
payload->state = RTP_OBJECT_READY;
rtp_object_in_stream_queue(payload, stream_ctx);
// TODO: use inter task communication
// wait payload state to IDEL or USED
rtsp_mod_wait_complete();
while(list_empty(&stream_ctx->output_queue))
vTaskDelay(1);
end:
exbuf->state = STAT_USED;
return 0;
}
msink_module_t rtsp_module =
{
.create = rtsp_mod_open,
.destroy = rtsp_mod_close,
.set_param = rtsp_mod_set_param,
.handle = rtsp_mod_handle,
};

View File

@@ -0,0 +1,257 @@
#include "mmf_sink.h"
//rtsp header files
#include "rtsp/rtsp_api.h"
#include "sockets.h"
#include "lwip/netif.h"
#define STREAM_FLOW_ID_BASE 0
static u32 stream_flow_id_bitmap = 0;
static _mutex stream_flow_id_bitmap_lock = NULL;
static int channel_idx=0;
//static int *codec_chennel_map; //
//static struct rtp_object *rtp_payload;
static struct __internal_payload{
int codec_id;
struct rtp_object payload;
}*rtpobj = NULL;
//static u32 rtsp_tick_offset = 0;
//static u32 rtsp_stream_num = 0;
// codec map
//
static int codec_map_v[] = {AV_CODEC_ID_MJPEG, AV_CODEC_ID_H264, AV_CODEC_ID_MP4V_ES};
static int codec_map_a[] = {AV_CODEC_ID_PCMU, AV_CODEC_ID_PCMA, AV_CODEC_ID_MP4A_LATM};
void rtsp2_mod_close(void* ctx)
{
struct rtsp_context * rtsp_ctx = (struct rtsp_context *)ctx;
for(int i=0;i<rtsp_ctx->nb_streams;i++){
if(rtsp_ctx->stream_ctx[i].codec)
free(rtsp_ctx->stream_ctx[i].codec);
rtp_object_deinit(&rtpobj[i].payload);
}
if(rtpobj)
free(rtpobj);
rtsp_close(rtsp_ctx);
rtsp_context_free(rtsp_ctx);
if(stream_flow_id_bitmap_lock != NULL)
rtw_mutex_free(&stream_flow_id_bitmap_lock);
stream_flow_id_bitmap = 0;
}
void* rtsp2_mod_open(void)
{
int timeout = 10;
struct rtsp_context *rtsp_ctx = rtsp_context_create(2);
if(!rtsp_ctx) return NULL;
/*open rtsp service task*/
if(rtsp_open(rtsp_ctx)<0){
rtsp_context_free(rtsp_ctx);
rtsp_ctx = NULL;
}
while(!rtsp_is_service_enabled(rtsp_ctx)){
rtw_mdelay_os(1000);
if(timeout--<=0){
printf("\n\rwait rtsp service time out...");
goto rtsp2_mod_open_fail;
}
}
rtpobj = malloc(sizeof(struct __internal_payload)*rtsp_ctx->nb_streams);
if(!rtpobj)
goto rtsp2_mod_open_fail;
// init payload object
for(int i=0;i<rtsp_ctx->nb_streams;i++){
rtp_object_init(&rtpobj[i].payload);
rtsp_ctx->stream_ctx[i].codec = malloc(sizeof(struct codec_info));
if(!rtsp_ctx->stream_ctx[i].codec)
goto rtsp2_mod_open_fail;
//rtsp_clock_init(rtsp_ctx->stream_ctx[i].codec->clock_rate);
}
return (void*)rtsp_ctx;
rtsp2_mod_open_fail:
//rtp_object_deinit(&rtp_payload);
rtsp2_mod_close(rtsp_ctx);
return NULL;
}
// to get stream id,
// need mutex to protect this routine? i dont think it is necessary
int rtsp2_mod_set_param(void* ctx, int cmd, int arg)
{
struct rtsp_context *rtsp_ctx = (struct rtsp_context *)ctx;
struct stream_context *stream_ctx = &rtsp_ctx->stream_ctx[channel_idx];
int *codec_map = NULL;
switch(cmd){
case CMD_SELECT_CHANNEL:
channel_idx = arg;
break;
case CMD_SET_FRAMERATE:
stream_ctx->framerate = arg;
break;
case CMD_SET_BITRATE:
stream_ctx->bitrate = arg;
break;
case CMD_SET_SAMPLERATE:
stream_ctx->samplerate = arg;
break;
case CMD_SET_CHANNEL:
stream_ctx->channel = arg;
break;
// for H264
case CMD_SET_SPS:
set_sps_string((char*)arg);
break;
case CMD_SET_PPS:
set_pps_string((char*)arg);
break;
case CMD_SET_LEVEL:
set_profile_lv_string((char*)arg);
break;
case CMD_SET_APPLY:
if(stream_flow_id_bitmap_lock == NULL)
rtw_mutex_init(&stream_flow_id_bitmap_lock);
if(stream_ctx->stream_id < 0)
stream_ctx->stream_id = rtsp_get_number(STREAM_FLOW_ID_BASE, &stream_flow_id_bitmap, &stream_flow_id_bitmap_lock);
rtp_stream_statistics_sync(stream_ctx);
rtpobj[channel_idx].codec_id = stream_ctx->codec->codec_id;
break;
/*
case CMD_SET_STREAMNUM:
if(arg>1){ // arg = 1, do nothing, because has been created when open
// free original stream
free(stream_ctx);
// malloc new steram and init
rtsp_ctx->nb_streams = arg;
rtsp_ctx->stream_ctx = malloc(arg * sizeof(struct stream_context));
if(!rtsp_ctx->stream_ctx) return -ENOMEM;
for(int i = 0; i < arg; i++)
{
rtsp_ctx->rtpseq[i] = 0;
rtsp_stream_context_init(rtsp_ctx, &rtsp_ctx->stream_ctx[i]);
}
}
break;
*/
case CMD_SET_STREAMMING:
if(arg == ON){
rtsp_clock_init(rtsp_ctx->stream_ctx[channel_idx].codec->clock_rate);
rtsp_start(rtsp_ctx);
// insert to input queue
for(int i=0;i<rtsp_ctx->nb_streams;i++)
rtp_object_in_stream_queue(&rtpobj[i].payload, &rtsp_ctx->stream_ctx[i]);
}else
rtsp_stop(rtsp_ctx);
break;
case CMD_SET_CODEC:
codec_map = ((arg&0xf0)==0x00)?codec_map_v:codec_map_a;
get_codec_by_id(stream_ctx->codec, codec_map[arg&0xf]);
stream_ctx->media_type = rtsp_parse_stream_media_type(stream_ctx->codec);
rtp_load_o_handler_by_codec_id(&rtpobj[channel_idx].payload, codec_map[arg&0xf]);
if(rtpobj[channel_idx].payload.rtp_object_handler == NULL)
return -EINVAL;
break;
case CMD_SET_FLAG:
if(arg == TIME_SYNC_DIS)
time_sync_disable();
else if(arg == TIME_SYNC_EN)
time_sync_enable();
break;
default:
break;
}
return 0;
}
// private function
int rtsp2_mod_wait_complete(void)
{
return 1;
}
// private function
int rtsp2_mod_compelete_cb(void)
{
return 1;
}
int rtsp2_mod_handle(void* ctx, void* b)
{
struct rtsp_context *rtsp_ctx = (struct rtsp_context *)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
struct stream_context *stream_ctx = NULL;
struct rtp_object *payload = NULL;//&rtp_payload;
if(exbuf->state != STAT_READY)
return -EAGAIN;
// get channel
int *codec_map = ((exbuf->codec_fmt&0xf0)==0x00)?codec_map_v:codec_map_a;
for(int i=0;i<rtsp_ctx->nb_streams;i++){
if(rtpobj[i].codec_id == codec_map[exbuf->codec_fmt&0xf]){
stream_ctx = &rtsp_ctx->stream_ctx[i];
break;
}
}
if(stream_ctx == NULL)
{
exbuf->state = STAT_INIT;
return -EFAULT;
}
if(rtsp_ctx->state != RTSP_PLAYING)
goto end;
// wait output not empty and get one
// Get payload from rtsp module
do{
payload = rtp_object_out_stream_queue(stream_ctx);
if(payload==NULL) vTaskDelay(1);
}while(payload == NULL);
// insert payload to rtsp_ctx stream
//printf("%d\n\r", xTaskGetTickCount());
/*fill payload*/
payload->index = exbuf->index;
payload->data = exbuf->data;
payload->len = exbuf->len;
//payload->timestamp = (rtw_get_current_time()-rtsp_tick_offset)*90;
payload->timestamp = exbuf->timestamp;//rtsp_get_current_tick();
//printf("ts: %8x\n\r", payload->timestamp);
/* because we will fill&send a complete frame in single rtp object, set both fs & fe to 1 and fd to 0*/
rtp_object_set_fs(payload, 1);
rtp_object_set_fe(payload, 1);
rtp_object_set_fd(payload, 0);
/* set payload state to READY to enable rtp task process this rtp object;*/
payload->state = RTP_OBJECT_READY;
rtp_object_in_stream_queue(payload, stream_ctx);
// TODO: use inter task communication
// wait payload state to IDEL or USED
rtsp2_mod_wait_complete();
while(list_empty(&stream_ctx->output_queue))
vTaskDelay(1);
end:
exbuf->state = STAT_USED;
return 0;
}
msink_module_t rtsp2_module =
{
.create = rtsp2_mod_open,
.destroy = rtsp2_mod_close,
.set_param = rtsp2_mod_set_param,
.handle = rtsp2_mod_handle,
};

View File

@@ -0,0 +1,32 @@
#ifndef _MEDIA_H
#define _MEDIA_H
#include "cmsis_os.h"
#include "mmf_common.h"
typedef struct _media_source_module{
void* (*create)(void);
void (*destroy)(void*);
int (*set_param)(void*, int, int);
int (*handle)(void*, void*); // input output will cast to exch_buf_t
}msrc_module_t;
typedef struct _media_source_context{
xQueueHandle input_qid;
xQueueHandle output_qid;
int state;
xTaskHandle hdl_task;
void* drv_priv;
msrc_module_t* source;
}msrc_context;
void mmf_source_close(msrc_context* ctx);
msrc_context* mmf_source_open(msrc_module_t* source);
int mmf_source_ctrl(msrc_context* ctx, int cmd, int arg);
int mmf_source_get_frame(msrc_context* ctx, exch_buf_t *exbuf);
// must be here
#include "mmf_source_modules/mmf_source_list.h"
#endif

View File

@@ -0,0 +1,96 @@
#include "mmf_source.h"
#include "sample_aac.h"
static unsigned int base_ts;
void* aacf_mod_open(void)
{
base_ts = xTaskGetTickCount();
return (void*)1;
}
void aacf_mod_close(void* ctx)
{
(void)ctx;
return;
}
int aacf_mod_set_param(void* ctx, int cmd, int arg)
{
(void)ctx;
(void)cmd;
(void)arg;
return 0;
}
static unsigned char* seek_to_next(unsigned char* ptr, unsigned char* ptr_end)
{
//ptr+=7;
while(ptr < ptr_end){
if(ptr[0]==0xff && (ptr[1]>>4)==0x0f)
break;
ptr++;
}
if(ptr>=ptr_end) return NULL;
unsigned char * temp = ptr+3;
u32 ausize = ((*temp&0x03)<<11)|(*(temp+1)<<3)|((*(temp+2)&0xe0)>>5);
ptr+=ausize;
if(ptr>=ptr_end)
return NULL;
else{
while(ptr < ptr_end){
if(ptr[0]==0xff && (ptr[1]>>4)==0x0f)
return ptr;
ptr++;
}
return NULL;
}
}
static unsigned char *sample = (unsigned char*)aac_sample;
static unsigned char *next_sample = (unsigned char *)aac_sample;
static u8 *ptr = NULL;
int aacf_mod_handle(void* ctx, void* b)
{
int ret = 0;
(void)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
/*get uvc buffer for new data*/
if(exbuf->state!=STAT_READY){
/*we will carry single AU for each rtp packet*/
sample = next_sample;
next_sample = seek_to_next(sample, (unsigned char*)aac_sample+aac_sample_size);
if(next_sample == NULL)
{
//replay
exbuf->len = aac_sample + aac_sample_size - sample;
next_sample = (unsigned char*)aac_sample;
}else{
exbuf->len = next_sample - sample;
}
exbuf->index = 0;
exbuf->data = sample;
//exbuf->timestamp = 0;
base_ts += 1024;
exbuf->timestamp = base_ts;
//vTaskDelay(500);
exbuf->state = STAT_READY;
}
return 0;
}
msrc_module_t aacf_module =
{
.create = aacf_mod_open,
.destroy = aacf_mod_close,
.set_param = aacf_mod_set_param,
.handle = aacf_mod_handle,
};

View File

@@ -0,0 +1,243 @@
#include "mmf_source.h"
//uvc/v4l2 header files
#include "videodev2.h"
#include "uvcvideo.h"
#include "v4l2_intf.h"
#include "driver/geo/patch_uvc_geo.h"
#define CHANNEL_CNT 4
static int chl_table[CHANNEL_CNT] = {0};
extern mux_stream_t mux_stream;
#define CLEAR(x) memset(&(x), 0, sizeof(x))
typedef struct __mxuvc_context{
int width;
int height;
int frame_rate;
int fmt_type;
int compression_ratio;
}mxuvc_context;
//------------------------------------------------------------------------------
void* geo_mod_open(void)
{
/*init usb driver prior to init uvc driver*/
_usb_init();
if(wait_usb_ready() < 0)
return NULL;
/*init uvc driver*/
if(uvc_stream_init() < 0)
// Maybe not correct
return NULL;
mxuvc_context *mxuvc_ctx = malloc(sizeof(mxuvc_context));
if(!mxuvc_ctx) return NULL;
// default value
mxuvc_ctx->fmt_type = V4L2_PIX_FMT_H264;
mxuvc_ctx->width = 1280;
mxuvc_ctx->height = 720;
mxuvc_ctx->frame_rate = 30;
mxuvc_ctx->compression_ratio = 0;
return mxuvc_ctx;
}
void geo_mod_close(void* ctx)
{
uvc_stream_free();
free((struct mxuvc_context *)ctx);
_usb_deinit();
}
int geo_mod_set_param(void* ctx, int cmd, int arg)
{
int i, ret = 0;
unsigned int temp = 0;
unsigned int frame = 0;
unsigned short width = 0;
unsigned short high = 0;
video_format_t format = 0;
mxuvc_context* mxuvc_ctx = (mxuvc_context*)ctx;
// format mapping
// FMT_V_MJPG FMT_V_H264
int codec_map[]={V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_H264};
switch(cmd){
case CMD_ENABLE_CHANNEL:
if(arg >= 0 && arg <= CHANNEL_CNT)
chl_table[arg] = 1;
break;
case CMD_DISABLE_CHANNEL:
if(arg >= 0 && arg <= CHANNEL_CNT)
chl_table[arg] = 0;
break;
case CMD_SET_HEIGHT:
mxuvc_ctx->height = arg;
break;
case CMD_SET_WIDTH:
mxuvc_ctx->width = arg;
break;
case CMD_SET_FRAMERATE:
mxuvc_ctx->frame_rate = arg;
break;
case CMD_SET_CPZRATIO:
mxuvc_ctx->compression_ratio = arg;
break;
case CMD_SET_FRAMETYPE:
mxuvc_ctx->fmt_type = codec_map[arg&0xF];
break;
case CMD_SET_APPLY:
//if(uvc_set_param(uvc_ctx->fmt_type, &uvc_ctx->width, &uvc_ctx->height, &uvc_ctx->frame_rate, &uvc_ctx->compression_ratio) < 0)
// ret = EIO;
break;
case CMD_SET_STREAMMING:
if(arg == ON){ // stream on
for(i = 0; i < CHANNEL_CNT; i++)
{
if(chl_table[i])
{
if(mxuvc_video_start(i) < 0)
ret = -EIO;
}
}
}else{ // stream off
for(i = 0; i < CHANNEL_CNT; i++)
{
if(!chl_table[i])
{
if(mxuvc_video_stop(i) < 0)
ret = -EIO;
}
}
}
break;
default:
ret = ENOTSUPP;
break;
}
return ret;
}
//static int first_packet = 0; //VLC need timestamps of each stream at the beginning of streaming
/* first_packet | state
* 0 | init state: allow all packets
* get audio / \ get video |
* 1 2 | 1: allow video; 2: allow audio
* get video \ / get audio |
* 3 | final: allow all packets
*/
int geo_mod_handle(void* ctx, void* b)
{
int ret = 0;
exch_buf_t *exbuf = (exch_buf_t*)b;
video_info_t info;
int channel_id;
uint8_t *data_buf;
uint32_t data_size;
uint64_t ts;
struct v4l2_buffer buf;
if(exbuf->state==STAT_USED){
memset(&buf, 0, sizeof(struct v4l2_buffer));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP /*V4L2_MEMORY_DMABUF*/;
buf.index = exbuf->index;
buf.field = /*V4L2_FIELD_ANY*/V4L2_FIELD_NONE;
buf.timestamp = rtw_get_current_time();
ret = v4l_usr_ioctl(mux_stream.fd, VIDIOC_QBUF, (void *)&buf);
if (ret < 0){
printf("\n\rread_frame mmap method enqueue buffer failed 1");
//mxuvc_video_stop(CH1);
return -EIO;
}
exbuf->state = STAT_INIT;
}
if(exbuf->state!=STAT_READY){
recap:
memset(&buf, 0, sizeof(struct v4l2_buffer));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP /*V4L2_MEMORY_DMABUF*/;
ret = v4l_usr_ioctl(mux_stream.fd, VIDIOC_DQBUF, (void *)&buf);
if (ret < 0){
printf("\r\nread_frame mmap method dequeue buffer failed 2");
//mxuvc_video_stop(CH1);
return -EIO;
}
/*manipulate buf data if necessary*/
CLEAR(info);
ret = qbox_parse_header((unsigned char*)buf.m.offset, &channel_id, &info.format, &data_buf, &data_size, &ts, &info.metadata);
//if((ret<0)||(channel_id == CH2)||(channel_id==CH1&&first_packet==2)||(channel_id==8&&first_packet==1)) {//can filter unwanted here //do not process H264 data from ch2
//if((ret<0)||(channel_id == CH2)||(channel_id==8)) {//can filter unwanted here //do not process H264 data from ch2
if((ret<0)||(channel_id == CH2)) {
ret = v4l_usr_ioctl(mux_stream.fd, VIDIOC_QBUF, (void *)&buf);
if (ret < 0){
printf("\r\nread_frame mmap method enqueue buffer failed 3");
//mxuvc_video_stop(CH1);
return -EIO;
}
goto recap;
}
int this_id = FMT_AV_UNKNOWN;
switch(info.format){
case VID_FORMAT_AAC_RAW:
this_id = FMT_A_MP4A_LATM;
break;
case VID_FORMAT_H264_TS:
case VID_FORMAT_H264_RAW:
this_id = FMT_V_H264;
break;
default:
printf("\r\nUnsupport format is met");
return -EOPNOTSUPP;
}
switch(this_id){
case FMT_A_MP4A_LATM:
//printf("AAC");
get_adts_header(data_size, data_buf);
exbuf->codec_fmt = FMT_A_MP4A_LATM;
break;
case FMT_V_H264:
//printf("H264");
exbuf->codec_fmt = FMT_V_H264;
break;
default:
printf("\r\nUnexpected error in event_handler");
break;
}
/*fill payload*/
exbuf->index = buf.index;
exbuf->data = data_buf;
exbuf->len = data_size;
if(this_id == FMT_A_MP4A_LATM){
exbuf->timestamp = (u32)( ts*16/90);//ts*16000/1000/90
}
else{
exbuf->timestamp = (u32) ts;
}
exbuf->state = STAT_READY;
}
return 0;
}
msrc_module_t geo_module =
{
.create = geo_mod_open,
.destroy = geo_mod_close,
.set_param = geo_mod_set_param,
.handle = geo_mod_handle,
};

View File

@@ -0,0 +1,84 @@
#include "mmf_source.h"
#include "sample_h264.h"
void* h264f_mod_open(void)
{
return (void*)1;
}
void h264f_mod_close(void* ctx)
{
(void)ctx;
return;
}
int h264f_mod_set_param(void* ctx, int cmd, int arg)
{
(void)ctx;
(void)cmd;
(void)arg;
return 0;
}
static unsigned char* seek_to_next(unsigned char* ptr, unsigned char* ptr_end)
{
ptr+=3;
while( ptr < ptr_end ){
if(ptr[0]==0 && ptr[1]==0){
if(ptr[2]==0 && ptr[3]==1 )
return ptr;
else if(ptr[2]==1)
return ptr;
}
ptr++;
}
return NULL;
}
static unsigned char *sample = (unsigned char*)h264_sample;
static unsigned char *next_sample = (unsigned char *)h264_sample;
u8 *ptr = NULL;
int h264f_mod_handle(void* ctx, void* b)
{
int ret = 0;
(void)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
/*get uvc buffer for new data*/
if(exbuf->state!=STAT_READY){
sample = next_sample;
ptr = sample;
next_sample = seek_to_next(sample, (unsigned char*)h264_sample+h264_sample_len);
if(next_sample == NULL)
{
//replay
exbuf->len = h264_sample + h264_sample_len - sample;
next_sample = (unsigned char*)h264_sample;
}else{
exbuf->len = next_sample - sample;
}
exbuf->index = 0;
exbuf->data = sample;
exbuf->timestamp = 0;
//vTaskDelay(500);
exbuf->state = STAT_READY;
}
return 0;
}
msrc_module_t h264f_module =
{
.create = h264f_mod_open,
.destroy = h264f_mod_close,
.set_param = h264f_mod_set_param,
.handle = h264f_mod_handle,
};

View File

@@ -0,0 +1,46 @@
#include "mmf_source.h"
#include "h264_encode.h"
void* h264_unit_open(void)
{
struct h264_context *h264_ctx = (struct h264_context *) malloc(sizeof(struct h264_context));
if (h264_ctx == NULL) {
return NULL;
}
memset(h264_ctx, 0, sizeof(struct h264_context));
h264_stream_init(h264_ctx);
h264_enc_init(h264_ctx);
//voe_init(h264_ctx);
//isp_init(h264_ctx);
return h264_ctx;
}
void h264_unit_close(void* ctx)
{
free((struct h264_context *)ctx);
}
int h264_unit_set_param(void* ctx, int cmd, int arg)
{
return 0;
}
int h264_unit_handle(void* ctx, void* b)
{
int ret = 0;
ret = h264_stream_get_frame(ctx, b);
return 0;
}
msrc_module_t h264_unit_module =
{
.create = h264_unit_open,
.destroy = h264_unit_close,
.set_param = h264_unit_set_param,
.handle = h264_unit_handle,
};

View File

@@ -0,0 +1,140 @@
#include "mmf_source_i2s_file.h"
static i2s_buf_context i2s_buf;
static u8 i2s_tx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM];
static u8 i2s_rx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM];
static unsigned char encoder_buf[G711_FSIZE];
static i2s_buf_context * buf_ctx=NULL;
static i2s_t i2s_obj;
static void set_i2s_buf_context(i2s_buf_context * des){
buf_ctx = des;
buf_ctx -> raw_data = i2s_rx_buf;
}
int i2s_mod_handle(void* ctx, void* b)
{
int ret = 0;
static unsigned int time_count = 0;
(void)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
unsigned char * source =i2s_buf.raw_data;
/*get uvc buffer for new data*/
if(exbuf->state!=STAT_READY){
G711_encoder((short *)(i2s_buf.raw_data+i2s_buf.data_start), encoder_buf, i2s_buf.mode, G711_FSIZE);
i2s_buf.data_start=(i2s_buf.data_start+2*G711_FSIZE)%(I2S_DMA_PAGE_SIZE*RECV_PAGE_NUM);
i2s_buf.len = (i2s_buf.data_end-i2s_buf.data_start+(I2S_DMA_PAGE_SIZE*RECV_PAGE_NUM))%(I2S_DMA_PAGE_SIZE*RECV_PAGE_NUM);
exbuf->len = G711_FSIZE;
exbuf->index = 0;
exbuf->data = encoder_buf;
time_count+=160;
exbuf->timestamp = time_count;
exbuf->state = STAT_READY;
}
return 0;
}
static void i2s_tx_complete(void *data, char* pbuf){
return ;
}
static void i2s_rx_complete(void *data, char* pbuf)
{
i2s_t *obj = (i2s_t *)data;
if(buf_ctx != NULL){// i2s write to buffer, rtsp read from buffer, so keeps len below half of the buffer
if(buf_ctx->len > I2S_DMA_PAGE_SIZE*RECV_PAGE_NUM/2){
buf_ctx->data_start = (buf_ctx->data_start+I2S_DMA_PAGE_SIZE) % (I2S_DMA_PAGE_SIZE*RECV_PAGE_NUM);
buf_ctx->len -=I2S_DMA_PAGE_SIZE;
}
buf_ctx->data_end = (buf_ctx->data_end+I2S_DMA_PAGE_SIZE) % (I2S_DMA_PAGE_SIZE*RECV_PAGE_NUM);
buf_ctx->len +=I2S_DMA_PAGE_SIZE;
}
i2s_recv_page(obj); // submit a new page for receive
return ;
}
void i2s_mod_init()
{
//i2s_t i2s_obj;
i2s_buf.len = i2s_buf.data_start = i2s_buf.data_end = 0;
set_i2s_buf_context(&i2s_buf);
vTaskDelay(1000);
alc5651_init();
alc5651_init_interface2(); // connect to ALC interface 2
i2s_obj.channel_num = CH_MONO;
i2s_obj.sampling_rate = SR_8KHZ;
i2s_obj.word_length = WL_16b;
i2s_obj.direction = I2S_DIR_RX;//TODO: need to check direction before i2s_set_dma_buffer
i2s_init(&i2s_obj, I2S_SCLK_PIN, I2S_WS_PIN, I2S_SD_PIN);
i2s_set_dma_buffer(&i2s_obj, (char*)i2s_tx_buf, (char*)i2s_rx_buf, \
I2S_DMA_PAGE_NUM, I2S_DMA_PAGE_SIZE);
i2s_tx_irq_handler(&i2s_obj, (i2s_irq_handler)i2s_tx_complete, (uint32_t)&i2s_obj);
i2s_rx_irq_handler(&i2s_obj, (i2s_irq_handler)i2s_rx_complete, (uint32_t)&i2s_obj);
/* rx need clock, let tx out first */
switch(i2s_obj.direction){
case I2S_DIR_TX:
i2s_send_page(&i2s_obj, (uint32_t*)i2s_get_tx_page(&i2s_obj));
break;
case I2S_DIR_TXRX:
i2s_send_page(&i2s_obj, (uint32_t*)i2s_get_tx_page(&i2s_obj));//don't break, need i2s_recv_page
case I2S_DIR_RX:
i2s_recv_page(&i2s_obj);
break;
default:
break;
}
}
void* i2s_mod_open(void)
{
i2s_mod_init();
return (void*)1;
}
void i2s_mod_close(void* ctx)
{
(void)ctx;
return;
}
int i2s_mod_set_param(void* ctx, int cmd, int arg)
{
int ret = 0;
switch(cmd){
case CMD_SET_FRAMETYPE:
if(arg == FMT_A_PCMU)
i2s_buf.mode = I2S_MODE_G711U;
else if(arg == FMT_A_PCMA)
i2s_buf.mode = I2S_MODE_G711A;
else
i2s_buf.mode = I2S_MODE_G711A;//default
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
msrc_module_t i2s_module =
{
.create = i2s_mod_open,
.destroy = i2s_mod_close,
.set_param = i2s_mod_set_param,
.handle = i2s_mod_handle,
};

View File

@@ -0,0 +1,35 @@
#ifndef MMF_SOURCE_I2S_FILE_H
#define MMF_SOURCE_I2S_FILE_H
#include "mmf_source.h"
#include "FreeRTOS.h"
#include "task.h"
//#include "example_rtsp_server_i2s.h"
#include "rtsp/rtsp_api.h"
#include "sockets.h"
#include "lwip/netif.h"
#include "i2s_api.h"
#include "alc5651.h"
#include "g711\g711_codec.h"
#include "gpio_api.h" // mbed
#include "gpio_irq_api.h"
#include <platform/platform_stdlib.h>
#include "platform_opts.h"
#include "dlist.h"
#include "basic_types.h"
#include "osdep_service.h"
#define I2S_DMA_PAGE_SIZE 320 // 2 ~ 4096
#define I2S_DMA_PAGE_NUM 4 // Vaild number is 2~4
#define RECV_PAGE_NUM I2S_DMA_PAGE_NUM
#define G711_FSIZE 160
#define I2S_MODE_SWITCH PE_5
#define I2S_SCLK_PIN PC_1
#define I2S_WS_PIN PC_0
#define I2S_SD_PIN PC_2
#endif /* MMF_SOURCE_I2S_FILE_H */

View File

@@ -0,0 +1,15 @@
#ifndef _MEDIA_MODULES_H
#define _MEDIA_MODULES_H
#include "../mmf_source.h"
//list all avaliable modules here
extern msrc_module_t uvc_module;
extern msrc_module_t geo_module;
extern msrc_module_t mjpgf_module;
extern msrc_module_t h264f_module;
extern msrc_module_t h264_unit_module;
extern msrc_module_t aacf_module;
extern msrc_module_t pcmuf_module;
extern msrc_module_t i2s_module;
extern msrc_module_t rtp_src_module;
#endif

View File

@@ -0,0 +1,60 @@
#include "mmf_source.h"
#include "sample_jpeg.h"
void* mjpgf_mod_open(void)
{
return (void*)1;
}
void mjpgf_mod_close(void* ctx)
{
(void)ctx;
return;
}
int mjpgf_mod_set_param(void* ctx, int cmd, int arg)
{
(void)ctx;
(void)cmd;
(void)arg;
return 0;
}
static int cnt = 0;
int mjpgf_mod_handle(void* ctx, void* b)
{
int ret = 0;
(void)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
/*get uvc buffer for new data*/
if(exbuf->state!=STAT_READY){
if(cnt++&0x1){
exbuf->data = (unsigned char *)PIC_320x240_2;
exbuf->len = PIC_LEN_2;
}else{
exbuf->data = (unsigned char *)PIC_320x240_1;
exbuf->len = PIC_LEN_1;
}
exbuf->index = 0;
exbuf->timestamp = 0;
//vTaskDelay(500);
exbuf->state = STAT_READY;
}
return 0;
}
msrc_module_t mjpgf_module =
{
.create = mjpgf_mod_open,
.destroy = mjpgf_mod_close,
.set_param = mjpgf_mod_set_param,
.handle = mjpgf_mod_handle,
};

View File

@@ -0,0 +1,72 @@
#include "mmf_source.h"
#include "sample_pcmu.h"
static unsigned int base_ts;
void* pcmuf_mod_open(void)
{
return (void*)1;
}
void pcmuf_mod_close(void* ctx)
{
(void)ctx;
return;
}
int pcmuf_mod_set_param(void* ctx, int cmd, int arg)
{
(void)ctx;
(void)cmd;
(void)arg;
return 0;
}
#define G711F_SIZE 160
static unsigned char *sample=(unsigned char *)pcmu_sample;
static unsigned char *next_sample=(unsigned char *)pcmu_sample;
int pcmuf_mod_handle(void* ctx, void* b)
{
int ret = 0;
(void)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
/*get uvc buffer for new data*/
if(exbuf->state!=STAT_READY){
unsigned char * source=(unsigned char*)pcmu_sample;
sample=next_sample;
if(sample-source >= pcmu_sample_size){//replay
sample = source;
next_sample = source+G711F_SIZE;
}
else{
next_sample+=G711F_SIZE;
if(next_sample - source >= pcmu_sample_size){
next_sample = source + pcmu_sample_size;
}
}
exbuf->len = next_sample-sample;
exbuf->index = 0;
exbuf->data = sample;
//exbuf->timestamp = 0;
base_ts += 160;
exbuf->timestamp = base_ts;
//vTaskDelay(500);
exbuf->state = STAT_READY;
}
return 0;
}
msrc_module_t pcmuf_module =
{
.create = pcmuf_mod_open,
.destroy = pcmuf_mod_close,
.set_param = pcmuf_mod_set_param,
.handle = pcmuf_mod_handle,
};

View File

@@ -0,0 +1,302 @@
#include "mmf_source.h"
#include "wifi_conf.h"
#include "lwip/api.h" //netconn use
#include <lwip/sockets.h>
#include "rtsp/rtp_api.h"
#define MAX_SELECT_SOCKET 8
#define DEFAULT_RTP_PORT 16384
#if CONFIG_EXAMPLE_MP3_STREAM_RTP
#define G711_BLK_SIZE (634)
#define AUDIO_BUF_SIZE (646) //160 BYTE DATA + 12 BYTE RTP HEADER
#else
#define G711_BLK_SIZE (160)
#define AUDIO_BUF_SIZE (172) //160 BYTE DATA + 12 BYTE RTP HEADER
#endif
#define AUDIO_BUF_DEPTH (4)
typedef struct rtp_exbuf_type
{
u8 buf[AUDIO_BUF_SIZE];
int len;
}rtp_exbuf_t;
typedef struct rtp_client_type
{
TaskHandle_t task_handle;
xQueueHandle cache_queue;
xQueueHandle done_queue;
struct connect_context connect_ctx;
_sema rtp_sema;
u8 rtp_shutdown;
}rtp_client_t;
//static u8* priv_buf[AUDIO_BUF_DEPTH];
static rtp_exbuf_t rtp_buf;
static int q_depth = 0;
static long listen_time_s = 0;
static long listen_time_us = 20000; //20ms
int rtp_client_start(void *param)
{
rtp_client_t *rtp_ctx = (rtp_client_t *)param;
u32 start_time, current_time;
int ret = 0;
int len, offset;
rtp_hdr_t rtp_header;
struct sockaddr_in rtp_addr;
socklen_t addrlen = sizeof(struct sockaddr_in);
fd_set read_fds;
struct timeval listen_timeout;
int mode = 0;
int opt = 1;
u16 last_seq = 0;
start_time = rtw_get_current_time();
wext_get_mode(WLAN0_NAME, &mode);
printf("\n\rwlan mode:%d", mode);
switch(mode)
{
case(IW_MODE_MASTER)://AP mode
while(wifi_is_ready_to_transceive(RTW_AP_INTERFACE) < 0)
{
vTaskDelay(1000);
current_time = rtw_get_current_time();
if((current_time - start_time) > 60000)
{
printf("\n\rwifi Tx/Rx not ready...");
return ret;
}
}
break;
case(IW_MODE_INFRA)://STA mode
case(IW_MODE_AUTO)://when ameba doesn't join bss
while(wifi_is_ready_to_transceive(RTW_STA_INTERFACE) < 0)
{
vTaskDelay(1000);
current_time = rtw_get_current_time();
if((current_time - start_time) > 60000)
{
printf("\n\rwifi Tx/Rx not ready...");
return ret;
}
}
break;
default:
printf("\n\rillegal wlan state!rtp client cannot start");
return ret;
}
wext_get_mode(WLAN0_NAME, &mode);
printf("\n\rwlan mode:%d", mode);
vTaskDelay(1000);
if((rtp_ctx->connect_ctx.socket_id = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
printf("\n\rcreate rtp client socket failed!");
return 0;//???
}
if((setsockopt(rtp_ctx->connect_ctx.socket_id, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt))) < 0){
printf("\r\n Error on setting socket option");
goto exit;
}
memset(&rtp_addr, 0, addrlen);
rtp_addr.sin_family = AF_INET;
rtp_addr.sin_addr.s_addr = INADDR_ANY;
rtp_addr.sin_port = htons(rtp_ctx->connect_ctx.server_port);
if (bind(rtp_ctx->connect_ctx.socket_id,(struct sockaddr *)&rtp_addr, addrlen)<0) {
printf("bind failed\r\n");
goto exit;
}
rtp_ctx->rtp_shutdown = 0;
while(!rtp_ctx->rtp_shutdown)
{
FD_ZERO(&read_fds);
listen_timeout.tv_sec = listen_time_s;
listen_timeout.tv_usec = listen_time_us;
FD_SET(rtp_ctx->connect_ctx.socket_id, &read_fds);
if(select(MAX_SELECT_SOCKET, &read_fds, NULL, NULL, &listen_timeout))
{
//q_depth = uxQueueSpacesAvailable(rtp_ctx->done_queue);
//if(q_depth > 0)
if(xQueueReceive(rtp_ctx->done_queue, (void *)&rtp_buf, 0xFFFFFFFF) != pdTRUE){
continue;
//insert silence here
}
//printf("\n\ro");
memset(rtp_buf.buf, 0, AUDIO_BUF_SIZE);
len = recvfrom(rtp_ctx->connect_ctx.socket_id, rtp_buf.buf, AUDIO_BUF_SIZE, 0, (struct sockaddr *)&rtp_addr, &addrlen);
rtp_buf.len = len;
xQueueSend(rtp_ctx->cache_queue, (void *)&rtp_buf, 0xFFFFFFFF);
}else{
//printf("\n\r.");
//insert silence here
}
}
exit:
close(rtp_ctx->connect_ctx.socket_id);
return ret;
}
void rtp_client_init(void *param)
{
rtp_client_t *rtp_ctx = (rtp_client_t *)param;
rtw_init_sema(&rtp_ctx->rtp_sema, 0);
while(1)
{
if(rtw_down_timeout_sema(&rtp_ctx->rtp_sema,100))
{
if(rtp_client_start(rtp_ctx) < 0)
goto exit;
}
}
exit:
rtp_ctx->rtp_shutdown = 0;
rtw_free_sema(&rtp_ctx->rtp_sema);
vTaskDelete(NULL);
}
void* rtp_mod_open(void)
{
rtp_client_t *rtp_ctx = malloc(sizeof(rtp_client_t));
if(rtp_ctx == NULL)
return NULL;
memset(rtp_ctx, 0, sizeof(rtp_client_t));
/* set default port */
rtp_ctx->connect_ctx.socket_id = -1;
rtp_ctx->connect_ctx.server_port = DEFAULT_RTP_PORT;
/* create a rtp client to receive audio data */
if(xTaskCreate(rtp_client_init, ((const char*)"rtp_client_init"), 512, rtp_ctx, 2, &rtp_ctx->task_handle) != pdPASS) {
//printf("\r\n geo_rtp_client_init: Create Task Error\n");
free(rtp_ctx);
return NULL;
}
return (void*)rtp_ctx;
}
void rtp_mod_close(void* ctx)
{
rtp_client_t *rtp_ctx = (rtp_client_t *)ctx;
if(!rtp_ctx->task_handle && xTaskGetCurrentTaskHandle()!=rtp_ctx->task_handle)
vTaskDelete(rtp_ctx->task_handle);
free(rtp_ctx);
}
int rtp_mod_set_param(void* ctx, int cmd, int arg)
{
int ret = 0;
rtp_client_t *rtp_ctx = (rtp_client_t *)ctx;
switch(cmd)
{
case(CMD_SET_PRIV_BUF):
if(arg==1)//initially set queue
{
rtp_ctx->cache_queue = xQueueCreate(AUDIO_BUF_DEPTH, sizeof(rtp_exbuf_t));
rtp_ctx->done_queue = xQueueCreate(AUDIO_BUF_DEPTH, sizeof(rtp_exbuf_t));
}else if(arg==2)//reset queue
{
xQueueReset(rtp_ctx->cache_queue);
xQueueReset(rtp_ctx->done_queue);
}else if(arg==0)//delete queue
{
vQueueDelete(rtp_ctx->cache_queue);
vQueueDelete(rtp_ctx->done_queue);
break;
}else{
ret = -EINVAL;
break;
}
for(int i = 0; i < AUDIO_BUF_DEPTH; i++)
{
xQueueSend(rtp_ctx->done_queue, (void*)&rtp_buf, 0xFFFFFFFF);
}
break;
case(CMD_SET_STREAMMING):
if(arg == ON){ // stream on
rtw_up_sema(&rtp_ctx->rtp_sema);
}else{ // stream off
rtp_ctx->rtp_shutdown = 0;
}
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
//give audio data here
rtp_exbuf_t tmp_exbuf[3];
static int tmp_order = 0;
static u16 last_seq = 0;
int rtp_mod_handle(void* ctx, void* b)
{
int ret = 0;
int q_depth = 0;
rtp_client_t *rtp_ctx = (rtp_client_t *)ctx;
exch_buf_t *exbuf = (exch_buf_t*)b;
rtp_hdr_t rtp_header;
int offset;
if(exbuf->state==STAT_USED){
xQueueSend(rtp_ctx->done_queue, (void *)&tmp_exbuf[exbuf->index], 0xFFFFFFFF);
exbuf->state = STAT_INIT;
}
//decide if audio cache is enough for send
q_depth = uxQueueSpacesAvailable(rtp_ctx->cache_queue);
//printf("\n\rQ-%d", q_depth);
if(q_depth >= AUDIO_BUF_DEPTH/2)
return -EAGAIN;
if(xQueueReceive(rtp_ctx->cache_queue, (void *)&tmp_exbuf[tmp_order], 0xFFFFFFFF) != pdTRUE)
return -EAGAIN;
offset = rtp_parse_header(tmp_exbuf[tmp_order].buf, &rtp_header, 1);
//printf("\n\r%d-%dB", offset, tmp_exbuf[tmp_order].len);
/* for data loss debugging */
#if 1
if(last_seq == 0)
last_seq = ntohs(rtp_header.seq);
else
{
if((ntohs(rtp_header.seq) - last_seq)>1)
printf("\n\r(%d-%d)", last_seq, ntohs(rtp_header.seq));
last_seq = ntohs(rtp_header.seq);
}
#endif
#if CONFIG_EXAMPLE_MP3_STREAM_RTP
if((rtp_header.pt == RTP_PT_PCMU) || (rtp_header.pt == RTP_PT_DYN_BASE) || (rtp_header.pt == RTP_PT_MPA))
#else
if(rtp_header.pt == RTP_PT_PCMU)
#endif
{
if(exbuf->state!=STAT_READY){
exbuf->index = tmp_order;
exbuf->data = tmp_exbuf[tmp_order].buf + offset;
exbuf->len = tmp_exbuf[tmp_order].len - offset;
//exbuf->timestamp = ?;
exbuf->state = STAT_READY;
tmp_order++;
if(tmp_order == 3)
tmp_order = 0;
}
}
return ret;
}
msrc_module_t rtp_src_module =
{
.create = rtp_mod_open,
.destroy = rtp_mod_close,
.set_param = rtp_mod_set_param,
.handle = rtp_mod_handle,
};

View File

@@ -0,0 +1,150 @@
#include "mmf_source.h"
//uvc/v4l2 header files
#include "videodev2.h"
#include "uvcvideo.h"
#include "v4l2_driver.h"
#include "uvc_intf.h"
void* uvc_mod_open(void)
{
/*init usb driver prior to init uvc driver*/
_usb_init();
if(wait_usb_ready() < 0)
return NULL;
/*init uvc driver*/
if(uvc_stream_init() < 0)
// Maybe not correct
return NULL;
struct uvc_context *uvc_ctx = malloc(sizeof(struct uvc_context));
if(!uvc_ctx) return NULL;
// default value
uvc_ctx->fmt_type = UVC_FORMAT_MJPEG;
uvc_ctx->width = 640;
uvc_ctx->height = 480;
uvc_ctx->frame_rate = 30;
uvc_ctx->compression_ratio = 0;
return uvc_ctx;
}
void uvc_mod_close(void* ctx)
{
uvc_stream_free();
free((struct uvc_context *)ctx);
_usb_deinit();
}
int uvc_mod_set_param(void* ctx, int cmd, int arg)
{
int ret = 0;
int *parg = NULL;
struct uvc_context* uvc_ctx = (struct uvc_context*)ctx;
// format mapping
// FMT_V_MJPG FMT_V_H264
int codec_map[]={UVC_FORMAT_MJPEG, UVC_FORMAT_H264};
switch(cmd){
case CMD_SET_HEIGHT:
uvc_ctx->height = arg;
break;
case CMD_SET_WIDTH:
uvc_ctx->width = arg;
break;
case CMD_SET_FRAMERATE:
uvc_ctx->frame_rate = arg;
break;
case CMD_SET_CPZRATIO:
uvc_ctx->compression_ratio = arg;
break;
case CMD_SET_FRAMETYPE:
uvc_ctx->fmt_type = codec_map[arg&0xF];
break;
case CMD_SET_APPLY:
if(uvc_set_param(uvc_ctx->fmt_type, &uvc_ctx->width, &uvc_ctx->height, &uvc_ctx->frame_rate, &uvc_ctx->compression_ratio) < 0)
ret = EIO;
break;
case CMD_GET_STREAM_READY:
parg = (int *)arg;
*parg = uvc_is_stream_ready();
break;
case CMD_GET_STREAM_STATUS:
parg = (int *)arg;
*parg = uvc_is_stream_on();
break;
case CMD_SET_STREAMMING:
if(arg == ON){ // stream on
if(uvc_stream_on() < 0)
ret = EIO;
}else{ // stream off
uvc_stream_off();
}
break;
default:
ret = ENOTSUPP;
break;
}
return ret;
}
int cnt = 0;
//#include "sample_jpeg.h"
int uvc_mod_handle(void* ctx, void* b)
{
int ret = 0;
exch_buf_t *exbuf = (exch_buf_t*)b;
struct uvc_buf_context buf;
if(exbuf->state==STAT_USED){
memset(&buf, 0, sizeof(struct uvc_buf_context));
buf.index = exbuf->index;
ret = uvc_qbuf(&buf);
exbuf->state = STAT_INIT;
}
/*get uvc buffer for new data*/
if(exbuf->state!=STAT_READY){
ret = uvc_dqbuf(&buf);
if(buf.index < 0){
return -EAGAIN;
}//empty buffer retrieved set payload state as IDLE
if((uvc_buf_check(&buf)<0)||(ret < 0)){
printf("\n\rbuffer error!");
uvc_stream_off();
return -EIO; // should return error
}
/*
if(cnt++&0x1){
exbuf->data = (unsigned char *)PIC_320x240_2;
exbuf->len = PIC_LEN_2;
}else{
exbuf->data = (unsigned char *)PIC_320x240_1;
exbuf->len = PIC_LEN_1;
}
*/
exbuf->index = buf.index;
exbuf->data = buf.data;
exbuf->len = buf.len;
exbuf->timestamp = 0;
//vTaskDelay(500);
exbuf->state = STAT_READY;
}
return 0;
}
msrc_module_t uvc_module =
{
.create = uvc_mod_open,
.destroy = uvc_mod_close,
.set_param = uvc_mod_set_param,
.handle = uvc_mod_handle,
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff