mirror of
https://github.com/jialexd/sdk-ameba-v4.0c_180328.git
synced 2026-07-06 19:45:46 +00:00
first add sdk
This commit is contained in:
commit
f91efd1250
3915 changed files with 1291882 additions and 0 deletions
137
component/common/media/framework/mmf_sink_modules/mmf_sink_i2s.c
Executable file
137
component/common/media/framework/mmf_sink_modules/mmf_sink_i2s.c
Executable 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,
|
||||
};
|
||||
10
component/common/media/framework/mmf_sink_modules/mmf_sink_list.h
Executable file
10
component/common/media/framework/mmf_sink_modules/mmf_sink_list.h
Executable 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
|
||||
109
component/common/media/framework/mmf_sink_modules/mmf_sink_mp3.c
Executable file
109
component/common/media/framework/mmf_sink_modules/mmf_sink_mp3.c
Executable 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,
|
||||
};
|
||||
19
component/common/media/framework/mmf_sink_modules/mmf_sink_mp3.h
Executable file
19
component/common/media/framework/mmf_sink_modules/mmf_sink_mp3.h
Executable 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 */
|
||||
210
component/common/media/framework/mmf_sink_modules/mmf_sink_mp4.c
Executable file
210
component/common/media/framework/mmf_sink_modules/mmf_sink_mp4.c
Executable 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,
|
||||
};
|
||||
215
component/common/media/framework/mmf_sink_modules/mmf_sink_rtsp.c
Executable file
215
component/common/media/framework/mmf_sink_modules/mmf_sink_rtsp.c
Executable 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,
|
||||
};
|
||||
257
component/common/media/framework/mmf_sink_modules/mmf_sink_rtsp2.c
Executable file
257
component/common/media/framework/mmf_sink_modules/mmf_sink_rtsp2.c
Executable 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,
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue