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

View File

@@ -0,0 +1,110 @@
#ifndef _MP4_ENCAP_H_
#define _MP4_ENCAP_H_
#include "basic_types.h"
#include "osdep_service.h"
#define MAX_BOX_CHILD 8
#define RBUF_SIZE 1024
typedef struct _mp4root{
unsigned int video_len;
unsigned int audio_len;
unsigned int total;
unsigned int keyindex;
}MP4root,*PMP4root;
#define STORAGE_IDLE 0
#define STORAGE_START 1
#define STORAGE_WRITE_ALL 2
#define STORAGE_WRITE_VIDEO 3
#define STORAGE_WRITE_AUDIO 4
#define STORAGE_STOP 5
#define STORAGE_END 6
#define STORAGE_ALL 0
#define STORAGE_VIDEO 1
#define STORAGE_AUDIO 2
typedef struct _mp4_payload{
unsigned char *addr;
unsigned int len;
}mp4_payload,pmp4_payload;
typedef struct _mp4_write_info{
int mp4_start_position;
int mp4_end_position;
int mp4_occupy_size;
int mp4_empty_size;
int mp4_write_start_position;
int mp4_write_end_position;
int mp4_write_occupy_size;
int mp4_write_empty_size;
int mp4_write_length;
}mp4_winfo,*pmp4_winfo;
typedef struct _mp4_context{
FATFS m_fs;
int drv_num;
char _drv[4];
FIL m_file;
char filename[32];
int Fatfs_ok;
int filecount;
int width;
int height;
int sample_rate;
int channel_count;
int frame_rate;
u32 start_time;//rtw_get_current_time()
u32 file_name_index;
u32 storage_state;
MP4root root;
MP4root root_reserve;
int period_time;
int file_total;
int sps_start;
int type;
int sps_len;
int pps_len;
int sps_pps_mark;
unsigned int *video_buffer_index;
unsigned int *video_buffer_size;
int video_size;
unsigned int *audio_buffer_index;
unsigned int *audio_buffer_size;
int audio_size;
unsigned char *moov_box;
int moov_box_size;
unsigned char *h264_buf;
int H264_LENGTH;
mp4_payload payload;
mp4_payload reserved_payload;
int reserved_start_index;
int iframe;
int reserved_type;
_sema start_fatfs_write;
int write_status;
int audio_write_status;
int video_write_status;
int buffer_write_status;//0: real write 1: virtual write
mp4_winfo winfo;
int nal_len;
int h264_extra_len;
int mp4_muxer_enable;
}mp4_context,*pmp4_context;
#define IDLE 0
#define FATFS_WRITING 1
#define FATFS_DONE 2
void mp4_handle(pmp4_context mp4_ctx,unsigned char *buf,unsigned int size,int type);
void set_mp4_audio_buffer(pmp4_context mp4_ctx,unsigned int *audio_index,unsigned int *audio_size,int size);
void set_mp4_video_buffer(pmp4_context mp4_ctx,unsigned int *video_index,unsigned int *video_size,int size);
void set_mp4_moov_buffer(pmp4_context mp4_ctx,unsigned char *moov,int size);
int mp4_set_record(pmp4_context mp4_ctx,int num);
void mp4_muxer_init(pmp4_context mp4_ctx);
void mp4_muxer_close(pmp4_context mp4_ctx);
int mp4_set_start_status(pmp4_context mp4_ctx);
#endif

View File

@@ -0,0 +1,42 @@
#ifndef _AAC_H
#define _AAC_H
#include "dlist.h" //list management
#include "basic_types.h"
#include "osdep_service.h"
//#include "osdep_api.h"
#define AAC_DEBUG 1
#if AAC_DEBUG
#define AAC_PRINTF(fmt, args...) printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#define AAC_ERROR(fmt, args...) printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#else
#define AAC_PRINTF(fmt, args...)
#define AAC_ERROR(fmt, args...)
#endif
struct rtp_au_hdr
{
u32 au_size; //contain AU size in octets(header length included)
#if 0
u16 au_index;
u16 au_index_delta;
u16 cts_flag;
u16 cts_delta;
u16 dts_flag;
u16 dts_delta;
u16 rap_flag;
u16 stream_state;
#endif
u32 au_header_len; //record AU header size in octets
};
struct rtp_aac_obj
{
u16 au_headers_len; //contain AU header size in octet (we will translate it into bit-wise count before sending)
u8 au_header_num; //contain AU header number
// struct rtp_au_hdr *au_hdr;
};
#endif /*_AAC_H*/

View File

@@ -0,0 +1,139 @@
#ifndef _AV_CODEC_H_
#define _AV_CODEC_H_
/* Is this the place to include different codec header for rtp usage?*/
struct codec_info
{
int codec_id;
const char codec_name[8];
u8 pt;
u32 clock_rate;
u8 audio_channels;
void *priv;
};
/* media type list -- range from 0-255 stored in 1 BYTE*/
#define AVMEDIA_TYPE_VIDEO 0
#define AVMEDIA_TYPE_AUDIO 1
#define AVMEDIA_TYPE_SUBTITLE 2
#define AVMEDIA_TYPE_UNKNOWN 255
/*codec id list -- id must match its placing order (starting from 0) in av_codec_tables*/
#define AV_CODEC_ID_MJPEG 0
#define AV_CODEC_ID_H264 1
#define AV_CODEC_ID_PCMU 2
#define AV_CODEC_ID_PCMA 3
#define AV_CODEC_ID_MP4A_LATM 4
#define AV_CODEC_ID_MP4V_ES 5
#define AV_CODEC_ID_UNKNOWN -1
/*rtp payload type mapping and standard rtp payload type table -- range from 0-255 in 1 BYTE*/
#define RTP_PT_PCMU 0
#define RTP_PT_GSM 3
#define RTP_PT_G723 4
#define RTP_PT_DVI4_R8000 5
#define RTP_PT_DVI4_R16000 6
#define RTP_PT_LPC 7
#define RTP_PT_PCMA 8
#define RTP_PT_G722 9
#define RTP_PT_L16_C2 10
#define RTP_PT_L16_C1 11
#define RTP_PT_QCELP 12
#define RTP_PT_CN 13
#define RTP_PT_MPA 14
#define RTP_PT_G728 15
#define RTP_PT_DVI4_R11025 16
#define RTP_PT_DVI4_R22050 17
#define RTP_PT_G719 18
#define RTP_PT_CELB 25
#define RTP_PT_JPEG 26
#define RTP_PT_NV 28
#define RTP_PT_H261 31
#define RTP_PT_MPV 32
#define RTP_PT_MP2T 33
#define RTP_PT_H263 34
#define RTP_PT_RTCP_BASE 72
#define RTP_PT_DYN_BASE 96
#define RTP_PT_UNKNOWN 255
/* AAC PROFILE */
#define AV_PROFILE_AAC_MAIN 0
#define AV_PROFILE_AAC_LOW 1
#define AV_PROFILE_AAC_SSR 2
#define AV_PROFILE_AAC_LTP 3
#define AV_PROFILE_AAC_HE 4
#define AV_PROFILE_AAC_HE_V2 28
#define AV_PROFILE_AAC_LD 22
#define AV_PROFILE_AAC_ELD 38
#define AV_PROFILE_MPEG2_AAC_LOW 128
#define AV_PROFILE_MPEG2_AAC_HE 131
#if 0
/* MPEG4 VIDEO PROFILE */
#define AV_PROFILE_MPEG4_SIMPLE 0
#define AV_PROFILE_MPEG4_SIMPLE_SCALABLE 1
#define AV_PROFILE_MPEG4_CORE 2
#define AV_PROFILE_MPEG4_MAIN 3
#define AV_PROFILE_MPEG4_N_BIT 4
#define AV_PROFILE_MPEG4_SCALABLE_TEXTURE 5
#define AV_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6
#define AV_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7
#define AV_PROFILE_MPEG4_HYBRID 8
#define AV_PROFILE_MPEG4_ADVANCED_REAL_TIME 9
#define AV_PROFILE_MPEG4_CORE_SCALABLE 10
#define AV_PROFILE_MPEG4_ADVANCED_CODING 11
#define AV_PROFILE_MPEG4_ADVANCED_CORE 12
#define AV_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13
#define AV_PROFILE_MPEG4_SIMPLE_STUDIO 14
#define AV_PROFILE_MPEG4_ADVANCED_SIMPLE 15
/* DTS */
#define AV_PROFILE_DTS 20
#define AV_PROFILE_DTS_ES 30
#define AV_PROFILE_DTS_96_24 40
#define AV_PROFILE_DTS_HD_HRA 50
#define AV_PROFILE_DTS_HD_MA 60
#define AV_PROFILE_DTS_EXPRESS 70
/* MPEG2 */
#define AV_PROFILE_MPEG2_422 0
#define AV_PROFILE_MPEG2_HIGH 1
#define AV_PROFILE_MPEG2_SS 2
#define AV_PROFILE_MPEG2_SNR_SCALABLE 3
#define AV_PROFILE_MPEG2_MAIN 4
#define AV_PROFILE_MPEG2_SIMPLE 5
/* H264 */
#define AV_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag
#define AV_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag
#define AV_PROFILE_H264_BASELINE 66
#define AV_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED)
#define AV_PROFILE_H264_MAIN 77
#define AV_PROFILE_H264_EXTENDED 88
#define AV_PROFILE_H264_HIGH 100
#define AV_PROFILE_H264_HIGH_10 110
#define AV_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA)
#define AV_PROFILE_H264_HIGH_422 122
#define AV_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA)
#define AV_PROFILE_H264_HIGH_444 144
#define AV_PROFILE_H264_HIGH_444_PREDICTIVE 244
#define AV_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA)
#define AV_PROFILE_H264_CAVLC_444 44
#endif
/*av codec tables*/
//#include "section_config.h"
//SDRAM_DATA_SECTION
static const struct codec_info av_codec_tables[] = {
{AV_CODEC_ID_MJPEG, "MJPEG", RTP_PT_JPEG, 90000, 0, 0},
{AV_CODEC_ID_H264, "H264", RTP_PT_DYN_BASE, 90000, 0, 0},
{AV_CODEC_ID_PCMU, "PCMU", RTP_PT_PCMU, 8000, 1, 0},
{AV_CODEC_ID_PCMA, "PCMA", RTP_PT_PCMA, 8000, 1, 0},
{AV_CODEC_ID_MP4A_LATM, "MP4A", RTP_PT_DYN_BASE, 16000, 2, 0},
{AV_CODEC_ID_MP4V_ES, "MP4V", RTP_PT_DYN_BASE, 90000, 0, 0},
};
#define AVCODEC_SIZE 6
void get_codec_by_id(struct codec_info *c, int id);
#endif //_AV_CODEC_H_

View File

@@ -0,0 +1,27 @@
#ifndef _G711_H
#define _G711_H
#include "dlist.h" //list management
#include "basic_types.h"
#include "osdep_service.h"
//#include "osdep_api.h"
#define G711_DEBUG 1
#if G711_DEBUG
#define G711_PRINTF(fmt, args...) printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#define G711_ERROR(fmt, args...) printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#else
#define G711_PRINTF(fmt, args...)
#define G711_ERROR(fmt, args...)
#endif
//struct rtp_g711_obj {
//};
/*for debug purpose*/
#endif /*_G711_H*/

View File

@@ -0,0 +1,75 @@
#ifndef _H264_H
#define _H264_H
#include "dlist.h" //list management
#include "basic_types.h"
#include "osdep_service.h"
//#include "osdep_api.h"
#define H264_DEBUG 0
#if H264_DEBUG
#define H264_PRINTF(fmt, args...) printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#define H264_ERROR(fmt, args...) printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#else
#define H264_PRINTF(fmt, args...)
#define H264_ERROR(fmt, args...)
#endif
#define MAX_NUM_NAL_PER_FRM 4
struct rtp_nal_obj
{
u8 start_code_len;
unsigned char nal_header;
u8 is_fu_start;
u8 is_fu_end;
u8 must_not_drop;
u8 do_not_send;
int offset;
};
struct rtp_h264_obj
{
int num_nal;
struct rtp_nal_obj nal_obj[MAX_NUM_NAL_PER_FRM];
};
#endif /*_H264_H*/
#if 0
#ifndef _H264_H
#define _H264_H
#include "dlist.h" //list management
#include "basic_types.h"
#include "osdep_service.h"
//#include "osdep_api.h"
#define H264_DEBUG 0
#if H264_DEBUG
#define H264_PRINTF(fmt, args...) printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#define H264_ERROR(fmt, args...) printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#else
#define H264_PRINTF(fmt, args...)
#define H264_ERROR(fmt, args...)
#endif
/* in favor of rtp fragmentation */
struct rtp_h264_obj
{
u8 start_code_len;
unsigned char nal_header;
u8 is_fu_start;
u8 is_fu_end;
u8 must_not_drop;
};
/********************************h264 over rtp******************************/
#endif /*_H264_H*/
#endif

View File

@@ -0,0 +1,62 @@
#ifndef _MJPEG_H
#define _MJPEG_H
#include "dlist.h" //list management
#include "basic_types.h"
#include "osdep_service.h"
//#include "osdep_api.h"
#define MJPEG_DEBUG 0
#if MJPEG_DEBUG
#define MJPEG_PRINTF(fmt, args...) printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#define MJPEG_ERROR(fmt, args...) printf("\n\r%s: " fmt, __FUNCTION__, ## args)
#else
#define MJPEG_PRINTF(fmt, args...)
#define MJPEG_ERROR(fmt, args...)
#endif
struct jpeghdr {
unsigned int tspec:8; /* type-specific field */
unsigned int off:24; /* fragment byte offset */
u8 type; /* id of jpeg decoder params */
u8 q; /* quantization factor (or table id) */
u8 width; /* frame width in 8 pixel blocks */
u8 height; /* frame height in 8 pixel blocks */
};
struct jpeghdr_rst {
u16 dri; /*restart interval*/
unsigned int f:1; /*restart first bit flag*/
unsigned int l:1; /*restart last bit flag*/
unsigned int count:14; /*restart count*/
};
struct jpeghdr_qtable {
u8 mbz;
u8 precision;
u16 length;
};
#define RTP_JPEG_RESTART 0x40
#define USE_EXPLICIT_DQT 128
#define USE_IMPLICIT_DQT 0
struct rtp_jpeg_obj
{
struct jpeghdr jpghdr;
struct jpeghdr_rst rsthdr;
struct jpeghdr_qtable qtable;
u8 lqt[64*2]; /* Luma Quantizer table */
u8 cqt[64*2]; /* Croma Quantizer table */
int hdr_len;
int frame_offset;
};
/*for debug purpose*/
void dumpJpegHeader(struct jpeghdr *jpghdr);
void dumpRstDeader(struct jpeghdr_rst *rsthdr);
#endif /*_MJPEG_H*/

View File

@@ -0,0 +1,27 @@
#ifndef MJPEG_2_JPEG_H
#define MJPEG_2_JPEG_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#ifndef AV_RB16
# define AV_RB16(x) \
((((const char*)(x))[0] << 8) | \
((const char*)(x))[1])
#endif
typedef struct AVFrames
{
char *FrameData;
int FrameLength;
}AVFrame;
static char *append(char *buf, const char *src, int size);
static char *append_dht_segment(char *buf);
void mjpeg2jpeg(AVFrame *in_frame);
#endif