initial commit
This commit is contained in:
111
lib/amb1_sdk/common/media/framework/mmf_common.h
Normal file
111
lib/amb1_sdk/common/media/framework/mmf_common.h
Normal 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
|
||||
30
lib/amb1_sdk/common/media/framework/mmf_sink.h
Normal file
30
lib/amb1_sdk/common/media/framework/mmf_sink.h
Normal 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
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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 */
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
32
lib/amb1_sdk/common/media/framework/mmf_source.h
Normal file
32
lib/amb1_sdk/common/media/framework/mmf_source.h
Normal 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
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
3200
lib/amb1_sdk/common/media/framework/mmf_source_modules/sample_aac.h
Normal file
3200
lib/amb1_sdk/common/media/framework/mmf_source_modules/sample_aac.h
Normal file
File diff suppressed because it is too large
Load Diff
34405
lib/amb1_sdk/common/media/framework/mmf_source_modules/sample_h264.h
Normal file
34405
lib/amb1_sdk/common/media/framework/mmf_source_modules/sample_h264.h
Normal file
File diff suppressed because it is too large
Load Diff
1429
lib/amb1_sdk/common/media/framework/mmf_source_modules/sample_jpeg.h
Normal file
1429
lib/amb1_sdk/common/media/framework/mmf_source_modules/sample_jpeg.h
Normal file
File diff suppressed because it is too large
Load Diff
14596
lib/amb1_sdk/common/media/framework/mmf_source_modules/sample_pcmu.h
Normal file
14596
lib/amb1_sdk/common/media/framework/mmf_source_modules/sample_pcmu.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user