Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
133
sdk/app/adkey_demo/adkey_demo.c
Normal file
133
sdk/app/adkey_demo/adkey_demo.c
Normal file
@@ -0,0 +1,133 @@
|
||||
#include "basic_include.h"
|
||||
#include "keyWork.h"
|
||||
#include "keyScan.h"
|
||||
#include "osal/msgqueue.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "stream_define.h"
|
||||
#include "osal/work.h"
|
||||
#include "user_work/user_work.h"
|
||||
#include "audio_msi/audio_adc.h"
|
||||
#include "fs/fatfs/osal_file.h"
|
||||
#include "file_process.h"
|
||||
struct msi *mp4_encode_msi2_init(const char *mp4_msi_name, uint8_t srcID, uint8_t filter_type, uint8_t rec_time, uint32_t audio_encode, struct file_process *file_process, uint8_t mode);
|
||||
struct msi *avi_encode_msi_init(const char *avi_msi_name, uint16_t filter_type, uint8_t rec_time);
|
||||
struct adkey_work
|
||||
{
|
||||
struct os_work wk;
|
||||
struct os_msgqueue key_demo_msg;
|
||||
struct msi *mp4_msi;
|
||||
struct msi *h264_msi;
|
||||
struct msi *avi_msi;
|
||||
};
|
||||
|
||||
static void *adkey_demo_mp4_file(struct file_process *file_process, char *filename, char *file_path, uint32_t file_size)
|
||||
{
|
||||
os_sprintf(filename, "0:key_mp4/%016d.mp4", (uint32_t) os_jiffies());
|
||||
void *fp = osal_fopen_auto((const char *) filename, "w+", 0);
|
||||
return fp;
|
||||
}
|
||||
static uint32_t push_key_demo(struct key_callback_list_s *callback_list, uint32_t keyvalue, uint32_t extern_value)
|
||||
{
|
||||
struct adkey_work *adkey_work = (struct adkey_work *) callback_list->priv;
|
||||
os_msgq_put(&adkey_work->key_demo_msg, keyvalue, 0);
|
||||
os_run_work(&adkey_work->wk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t adkey_demo_work(struct os_work *work)
|
||||
{
|
||||
struct adkey_work *adkey_work = (struct adkey_work *) work;
|
||||
uint32_t val;
|
||||
int32 err;
|
||||
val = os_msgq_get2(&adkey_work->key_demo_msg, 0, &err);
|
||||
if (!err)
|
||||
{
|
||||
if ((val & 0xff) == KEY_EVENT_SUP)
|
||||
{
|
||||
switch (val >> 8)
|
||||
{
|
||||
case AD_UP:
|
||||
if (!adkey_work->mp4_msi)
|
||||
{
|
||||
|
||||
struct file_process adkey_demo_file_process = {
|
||||
.loop = NULL,
|
||||
.rec_path = NULL,
|
||||
.ext_name = NULL,
|
||||
.create_file = adkey_demo_mp4_file,
|
||||
.loop_free = NULL,
|
||||
.lock_file = NULL,
|
||||
};
|
||||
|
||||
adkey_work->h264_msi = msi_find(AUTO_H264, 1);
|
||||
adkey_work->mp4_msi = mp4_encode_msi2_init("ad_mp4", FRAMEBUFF_SOURCE_CAMERA0, FSTYPE_H264_VPP_DATA0, 1, 0, &adkey_demo_file_process, 0);
|
||||
if (adkey_work->h264_msi && adkey_work->mp4_msi)
|
||||
{
|
||||
msi_add_output(adkey_work->h264_msi, NULL, adkey_work->mp4_msi->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (adkey_work->h264_msi)
|
||||
{
|
||||
msi_put(adkey_work->h264_msi);
|
||||
adkey_work->h264_msi = NULL;
|
||||
}
|
||||
if (adkey_work->mp4_msi)
|
||||
{
|
||||
msi_destroy(adkey_work->mp4_msi);
|
||||
adkey_work->mp4_msi = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (adkey_work->h264_msi)
|
||||
{
|
||||
msi_del_output(adkey_work->h264_msi, NULL, adkey_work->mp4_msi->name);
|
||||
msi_put(adkey_work->h264_msi);
|
||||
adkey_work->h264_msi = NULL;
|
||||
}
|
||||
if (adkey_work->mp4_msi)
|
||||
{
|
||||
msi_destroy(adkey_work->mp4_msi);
|
||||
adkey_work->mp4_msi = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AD_DOWN:
|
||||
{
|
||||
if (!adkey_work->avi_msi)
|
||||
{
|
||||
adkey_work->avi_msi = avi_encode_msi_init("ad_avi", (uint16_t) ~0, 60 * 1);
|
||||
if (adkey_work->avi_msi)
|
||||
{
|
||||
msi_add_output(NULL, R_GEN420_JPG_RECODE, adkey_work->avi_msi->name);
|
||||
auadc_msi_add_output(AUSYS_AUAD, adkey_work->avi_msi->name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msi_del_output(NULL, R_GEN420_JPG_RECODE, adkey_work->avi_msi->name);
|
||||
auadc_msi_del_output(AUSYS_AUAD, adkey_work->avi_msi->name);
|
||||
msi_destroy(adkey_work->avi_msi);
|
||||
adkey_work->avi_msi = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void adkey_work_init()
|
||||
{
|
||||
struct adkey_work *adkey_work = (struct adkey_work *) os_zalloc(sizeof(struct adkey_work));
|
||||
os_msgq_init(&adkey_work->key_demo_msg, 5);
|
||||
OS_WORK_INIT(&adkey_work->wk, adkey_demo_work, 0);
|
||||
add_keycallback(push_key_demo, adkey_work);
|
||||
}
|
||||
75
sdk/app/algorithm/pdmFilter/pdmFilter.c
Normal file
75
sdk/app/algorithm/pdmFilter/pdmFilter.c
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "typesdef.h"
|
||||
#include "pdmFilter.h"
|
||||
/** @brief 去直流函数,使用一阶切比雪夫1型高通滤波器,fpass=20
|
||||
* @{
|
||||
*/
|
||||
#define FIXED_POINT_NUM 30
|
||||
//增加IIR缓存数据的小数位数,减少噪声
|
||||
#define FRAC_FIXED_NUM 12
|
||||
|
||||
const int NUM[2][2] = {
|
||||
{ 1072963942, 0, },
|
||||
{ 1073741824, -1073741824 },
|
||||
};
|
||||
const int DEN[2][2] = {
|
||||
{ 1073741824, 0, },
|
||||
{ 1073741824, -1072186059, },
|
||||
};
|
||||
|
||||
|
||||
int16_t rm_dc_filter(TYPE_FIRST_ORDER_FILTER_TYPE *p_filter, int16_t input)
|
||||
{
|
||||
int x = input << FRAC_FIXED_NUM;
|
||||
int y;
|
||||
int64_t acc;
|
||||
|
||||
acc = (int64_t)x * (int64_t)NUM[0][0];
|
||||
if(acc < 0) {
|
||||
x = (acc + (1<<FIXED_POINT_NUM) - 1) >> FIXED_POINT_NUM;
|
||||
} else {
|
||||
x = acc >> FIXED_POINT_NUM;
|
||||
}
|
||||
|
||||
acc = (int64_t)x * (int64_t)NUM[1][0];
|
||||
acc += (int64_t)p_filter->x * (int64_t)NUM[1][1];
|
||||
acc -= (int64_t)p_filter->y * (int64_t)DEN[1][1];
|
||||
if(acc < 0) {
|
||||
y = (acc + (1<<FIXED_POINT_NUM) - 1) >> FIXED_POINT_NUM;
|
||||
} else {
|
||||
y = acc >> FIXED_POINT_NUM;
|
||||
}
|
||||
|
||||
p_filter->x = x;
|
||||
p_filter->y = y;
|
||||
|
||||
y >>= FRAC_FIXED_NUM;
|
||||
|
||||
//饱和操作
|
||||
if(y > 32767) {
|
||||
y = 32767;
|
||||
} else if(y < -32768) {
|
||||
y = -32768;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @brief 音量控制。注意gain为 bit 定点数
|
||||
* @{
|
||||
*/
|
||||
int16_t pcm_volum_gain(int16_t input, int32_t gain)
|
||||
{
|
||||
int32_t temp = (input * gain) >> 8;
|
||||
if(temp > 32767) {
|
||||
return 32767;
|
||||
} else if(temp < -32768) {
|
||||
return -32768;
|
||||
} else {
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
11
sdk/app/algorithm/pdmFilter/pdmFilter.h
Normal file
11
sdk/app/algorithm/pdmFilter/pdmFilter.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef __PDMFILTER_H
|
||||
#define __PDMFILTER_H
|
||||
#include "typesdef.h"
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
} TYPE_FIRST_ORDER_FILTER_TYPE;
|
||||
|
||||
int16_t rm_dc_filter(TYPE_FIRST_ORDER_FILTER_TYPE *p_filter, int16_t input);
|
||||
int16_t pcm_volum_gain(int16_t input, int32_t gain);
|
||||
#endif
|
||||
459
sdk/app/algorithm/stream_frame/stream_define.h
Normal file
459
sdk/app/algorithm/stream_frame/stream_define.h
Normal file
@@ -0,0 +1,459 @@
|
||||
#ifndef __STREAM_DEFINE_H
|
||||
#define __STREAM_DEFINE_H
|
||||
|
||||
// 用于定义各种data的类型枚举
|
||||
enum
|
||||
{
|
||||
DATA_TYPE_ANY,
|
||||
DATA_TYPE_AUDIO_PDM,
|
||||
DATA_TYPE_AUDIO_I2S,
|
||||
DATA_TYPE_AUDIO_ADC,
|
||||
DATA_TYPE_AUDIO_DAC,
|
||||
DATA_TYPE_JPEG_VGA,
|
||||
DATA_TYPE_JPEG_720P,
|
||||
};
|
||||
|
||||
// 定义各种流的名称,R开头代表接收的流,S开头是发送的流,SR代表既要接收又要发送的流
|
||||
// 名称不能相同
|
||||
|
||||
// 没有专门发送和接收,只是流负责管理
|
||||
#define MANAGE_STREAM_NAME "manage-stream"
|
||||
// R
|
||||
#define R_RECORD_AUDIO "record-audio" // 录像的音频
|
||||
#define R_RECORD_JPEG "record-jpeg" // 录像的音频
|
||||
#define R_RECORD_H264 "record-h264" // 录像的音频
|
||||
#define R_PHOTO_JPEG "photo-jpeg" // 录像的音频
|
||||
#define R_ALK_JPEG "alk-jpeg"
|
||||
#define R_AUDIO_TEST "audio-test"
|
||||
#define R_SPEAKER "speaker"
|
||||
#define R_JPEG_TO_LCD "JPEG-LCD"
|
||||
#define R_JPEG_DEMO "jpeg_demo"
|
||||
#define R_USB_AUDIO_MIC "usb-audio-mic"
|
||||
#define R_RTP_AUDIO "rtp-audio" // 图传的音频
|
||||
#define R_RTP_AUDIO2 "rtp-audio2" // 图传的音频
|
||||
#define R_RTP_JPEG "rtp-jpeg" // 图传的视频
|
||||
#define R_RTP_JPEG_H264 "rtp-jpeg-h264" // 图传的视频
|
||||
#define R_LVGL_JPEG "lvgl-jpeg" // lvgl接收回放适配
|
||||
#define R_LVGL_TAKEPHOTO "lvgl_takephoto"
|
||||
#define R_LOWPOERRESUME_EVENT "LOWPOERRESUME_EVENT"
|
||||
#define R_AT_SAVE_OSD "AT_OSD"
|
||||
#define R_AT_SAVE_AUDIO "AT_AUDIO"
|
||||
#define R_AT_SAVE_PHOTO "AT_PHOTO"
|
||||
#define R_AT_AVI_AUDIO "AT_AVI_AUDIO" // 录像的音频
|
||||
#define R_AT_AVI_JPEG "AT_AVI_JPEG" // 录像的音频
|
||||
#define R_SAVE_STREAM_DATA "stream_data"
|
||||
#define R_INTERMEDIATE_DATA "R_Intermediate_data"
|
||||
#define R_AVI_SAVE_VIDEO "AVI_SAVE_VIDEO"
|
||||
#define R_AVI_SAVE_AUDIO "AVI_SAVE_AUDIO"
|
||||
#define R_INTERCOM_AUDIO "INTERCOM_SEND"
|
||||
#define R_PSRAM_JPEG "PSRM-jpeg" // 接收到psram的视频
|
||||
#define R_USB_SPK "usb_speaker"
|
||||
#define R_OSD_ENCODE "osd_encode"
|
||||
#define R_OSD_SHOW "osd_show"
|
||||
#define R_LCD_OSD "LCD_OSD"
|
||||
#define R_CSC_VIDEO_P2 "CSC_VIDEO_P2"
|
||||
#define R_VIDEO_P1 "VIDEO_P1"
|
||||
#define R_VIDEO_P0 "VIDEO_P0"
|
||||
#define R_SIM_VIDEO "SIM_VIDEO"
|
||||
#define R_JPG_TO_RGB "JPG_TO_RGB"
|
||||
#define R_YUV_TO_JPG "YUV_TO_JPG"
|
||||
#define R_ZBAR "Zbar"
|
||||
#define R_PRC "prc"
|
||||
#define RS_JPG_CONCAT "JPG_CONCAT" // 用于jpg重新组成framebuff
|
||||
#define RS_JPG_CONCAT1 "JPG_CONCAT1" // 用于jpg1重新组成framebuff
|
||||
#define R_GEN420_THUMB_JPG "gen420_thumb_jpg"
|
||||
#define R_GEN420_THUMB_JPG_USB "gen420_thumb_jpg_usb"
|
||||
#define R_GEN420_THUMB_JPG_OVER_DPI "gen420_thumb_jpg_over_dpi"
|
||||
#define R_GEN420_JPG_RECODE "gen420_JPG_RECODE"
|
||||
#define R_SCALE1_JPG_RECODE "scale1_JPG_RECODE"
|
||||
#define R_DEBUG_STREAM "debug_stream"
|
||||
#define R_SONIC_PROCESS "r_sonic_process"
|
||||
#define R_JPG_THUMB "JPG_THUMB"
|
||||
#define R_JPG_PHOTO_USB "JPG_PHOTO_USB"
|
||||
#define R_MP4_THUMB "MP4_THUMB"
|
||||
#define R_AVI_THUMB "AVI_THUMB"
|
||||
#define R_THUMB "THUMB"
|
||||
#define R_THUMB_USB "THUMB_USB"
|
||||
#define R_JPG_SAVE "JPG_SAVE"
|
||||
#define R_JPG_DECODE_MSG "JPG_DECODE_MSG"
|
||||
#define R_THUMB_DECODE_MSG "THUMB_DECODE_MSG"
|
||||
#define R_THUMB_DECODE_MSG_USB "THUMB_DECODE_MSG_USB"
|
||||
#define R_USBD_VIDEO "usbd_video_msi"
|
||||
#define R_FILE_MSI "file_msi"
|
||||
#define R_RTP_H264 "rtp-h264" // 图传的视频
|
||||
#define R_AVI_ENCODE_MSI "avi_encode_msi"
|
||||
#define R_CSC_MSI "csc_msi"
|
||||
// S
|
||||
#define S_PDM "pdm"
|
||||
#define S_ADC_AUDIO "adc_audio"
|
||||
#define S_MP3_AUDIO "mp3_audio"
|
||||
#define S_AMRNB_AUDIO "amrnb_audio"
|
||||
#define S_AMRWB_AUDIO "amrwb_audio"
|
||||
#define S_JPEG "jpeg"
|
||||
#define S_USB_JPEG "usb-jpeg"
|
||||
#define S_USB_JPEG_PSRAM "usb-jpeg-psram"
|
||||
#define S_WEBJPEG "web-jpeg"
|
||||
#define S_PLAYBACK "playback-jpeg"
|
||||
#define S_WEBAUDIO "web-audio"
|
||||
#define S_NET_JPEG "net-jpeg"
|
||||
#define S_USB_DUAL "usb-dual"
|
||||
#define S_INTERCOM_AUDIO "INTERCOM_RECV"
|
||||
#define S_INTERMEDIATE_DATA "S_Intermediate_data"
|
||||
#define S_USB_MIC "usb_microphone"
|
||||
#define S_LVGL_OSD "lvgl_osd"
|
||||
#define S_JPG_DECODE "jpg_decode"
|
||||
#define S_LVGL_JPG "lvgl_jpg"
|
||||
#define S_PREVIEW_SCALE3 "preview_scale3"
|
||||
#define S_SCALE1_STREAM "scale1_stream"
|
||||
#define S_PREVIEW_ENCODE_QVGA "preview_encode_qvga"
|
||||
#define S_PREVIEW_ENCODE_QQVGA "preview_encode_qqvga"
|
||||
#define S_PREVIEW_ENCODE_VPP "preview_encode_vpp"
|
||||
#define S_SONIC_PROCESS "s_sonic_process"
|
||||
#define S_NEWPLAYER "newplayer"
|
||||
#define S_NEWAVI "newavi"
|
||||
#define S_ZBAR_FROM_SD "zbar_read_sd"
|
||||
#define S_LVGL_PHOTO "lvgl_photo"
|
||||
#define S_LVGL_OSD "lvgl_osd"
|
||||
#define S_SCALE3_OVER_DPI "scale3_over_dpi"
|
||||
#define S_H264 "h264"
|
||||
#define S_SCALE3_720P "scale3_720p"
|
||||
#define S_AVI_PLAYER "avi_player"
|
||||
#define S_DEBUG_STREAM "s_debug_stream"
|
||||
|
||||
// SR
|
||||
#define SR_OTHER_JPG "other_jpg"
|
||||
#define SR_OTHER_JPG_USB1 "other_jpg_usb1"
|
||||
#define SR_OTHER_JPG_USB2 "other_jpg_usb2"
|
||||
#define SR_OTHER_JPG_USB3 "other_jpg_usb3"
|
||||
#define SR_USB_RECODE_DEOCDE "usb_recode_decode"
|
||||
#define SR_YUV_WATERMARK "YUV_watermark"
|
||||
#define SR_VIDEO_USB "video_usb"
|
||||
#define SR_ZBAR_JPG "zbar_parse"
|
||||
#define SR_OVER_DPI_JPG "over_dpi_jpg"
|
||||
#define SR_OVER_DPI_THUMB_JPG "over_dpi_thumb"
|
||||
#define SR_GEN420_720P_JPG "GEN420_720P_MJPG"
|
||||
#define ROUTE_USB "route-usb"
|
||||
#define AUTO_JPG "auto-jpg"
|
||||
#define AUTO_JPG1 "auto-jpg1"
|
||||
#define AUTO_H264 "auto-h264"
|
||||
|
||||
// 高16位是大类型(统一宏),低16位是细分类型
|
||||
#define SET_DATA_TYPE(type1, type2) (type1 << 16 | type2)
|
||||
#define GET_DATA_TYPE1(type) (type >> 16)
|
||||
#define GET_DATA_TYPE2(type) (type & 0xffff)
|
||||
|
||||
enum data_type1
|
||||
{
|
||||
TYPE1_NONE,
|
||||
JPEG = 1,
|
||||
SOUND,
|
||||
H264,
|
||||
|
||||
};
|
||||
|
||||
// 0保留
|
||||
enum DATA_TYPE2_RECV_ALL
|
||||
{
|
||||
RESEVER_VALUE,
|
||||
RECV_ALL = RESEVER_VALUE,
|
||||
};
|
||||
|
||||
// 定义mjpeg的类型,最好自己将不同类型归类
|
||||
enum JPEG_data_type2
|
||||
{
|
||||
JPEG_DVP_NODE = RESEVER_VALUE + 1, // 采用特殊的节点方式
|
||||
JPEG_DVP_FULL, // 采用整张图保存的方式(在空间足够下,采用正常图片形式,正常是带psram才会使用)
|
||||
JPEG_USB,
|
||||
JPEG_FILE,
|
||||
};
|
||||
|
||||
// 定义声音的类型
|
||||
enum SOUND_data_type2
|
||||
{
|
||||
SOUND_ALL = RECV_ALL,
|
||||
SOUND_NONE, // 不接收声音,源头不要产生这个声音就好了
|
||||
SOUND_MIC,
|
||||
SOUND_FILE,
|
||||
SOUND_USB_SPK,
|
||||
};
|
||||
|
||||
// 设置发送的命令,只有type1是在这里定义,type2由各个模块去定义(这个就不再有固定,因为自定义,所以在要自己在各个STREAM_SEND_CMD里面去处理识别)
|
||||
|
||||
#define SET_CMD_TYPE(type1, type2) (type1 << 16 | type2)
|
||||
#define GET_CMD_TYPE1(type) (type >> 16)
|
||||
#define GET_CMD_TYPE2(type) (type & 0xffff)
|
||||
|
||||
enum cmd_type1
|
||||
{
|
||||
CMD_NONE,
|
||||
CMD_AUDIO_DAC,
|
||||
CMD_JPEG_FILE,
|
||||
};
|
||||
|
||||
struct jpg_node_s
|
||||
{
|
||||
uint16_t w, h;
|
||||
uint32_t jpg_len;
|
||||
};
|
||||
|
||||
struct fb_h264_s
|
||||
{
|
||||
uint8_t *pps;
|
||||
uint8_t *sps;
|
||||
uint16_t pps_len;
|
||||
uint16_t sps_len;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
uint8_t count;
|
||||
uint8_t type; // 0:无效 1:I帧 2:P帧 3:B帧
|
||||
uint8_t start_len; // 读取实际内容的的起始长度(就是偏移到I帧、P帧、B帧头第一byte)
|
||||
};
|
||||
|
||||
enum YUV_ARG_TYPE
|
||||
{
|
||||
YUV_ARG_NONE,
|
||||
YUV_ARG_NORMAL,
|
||||
YUV_ARG_DECODE,
|
||||
YUV_ARG_TAKEPHOTO,
|
||||
};
|
||||
// yuv通用参数
|
||||
struct yuv_arg_s
|
||||
{
|
||||
uint32_t type; // 不同类型的yuv代表携带的信息不一致?(暂时没有想到更好方法,暂时通过这个去识别,如果某些模块只要yuv,是可以不识别的)
|
||||
uint32_t y_size;
|
||||
uint32_t y_off;
|
||||
uint32_t uv_off;
|
||||
uint32_t out_w;
|
||||
uint32_t out_h;
|
||||
// 状态位,如果发现要求del,那么接收流就要尽快释放了,不要占用当前节点
|
||||
uint16_t x, y;
|
||||
uint8_t *del;
|
||||
uint32_t dispcnt;
|
||||
uint32_t magic; // 一个类似随机数?有些msi可以通过识别这个magic来判断是否为自己所需要的数据};
|
||||
uint8_t video_only; //多屏显示层专用,用于只显示当前层画面
|
||||
};
|
||||
|
||||
// 解码,yuv通用参数放前面,与yuv_arg_s保持一致
|
||||
struct jpg_decode_arg_s
|
||||
{
|
||||
struct yuv_arg_s yuv_arg;
|
||||
uint32_t rotate;
|
||||
uint32_t decode_w; // 解码图片的size
|
||||
uint32_t decode_h;
|
||||
uint32_t step_w;
|
||||
uint32_t step_h;
|
||||
};
|
||||
|
||||
struct takephoto_yuv_arg_s
|
||||
{
|
||||
struct yuv_arg_s yuv_arg;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
enum YUV_data_type2
|
||||
{
|
||||
YUV_P0 = BIT(0),
|
||||
YUV_P1 = BIT(1),
|
||||
// 如果YUV需要编码,那么值可能与JPG的值会有关联,这个要好好想想怎么去处理
|
||||
YUV_OTHER = BIT(2),
|
||||
};
|
||||
|
||||
struct file_msg_s
|
||||
{
|
||||
uint32_t type;
|
||||
uint8_t path[64];
|
||||
uint8_t ishid;
|
||||
};
|
||||
|
||||
enum JPG_HARDWARE_data_type2
|
||||
{
|
||||
// 暂定双镜头,如果有更多需要区分,可以先添加
|
||||
JPG_Camera0 = BIT(0),
|
||||
JPG_Camera1 = BIT(1),
|
||||
// 下面算是自定义,比如gen420可以从各个地方来源,所以没有固定的名字
|
||||
// 这里可能部分需要与YUV一致?因为编码从GEN420过来的,所以类型会与GEN420的源头会有关联
|
||||
// 如果有关联,就要考虑映射关系了,暂时先直接用吧
|
||||
JPG_GEN420_0 = BIT(2),
|
||||
};
|
||||
|
||||
enum RGB_data_type2
|
||||
{
|
||||
LVGL_RGB = BIT(0),
|
||||
};
|
||||
|
||||
// MSI的命令暂时定义这里,后续需要整理
|
||||
enum MSI_SELF_CMDs
|
||||
{
|
||||
// osd使用
|
||||
MSI_OSD_HARDWARE_REAY_CMD,
|
||||
MSI_OSD_HARDWARE_ENCODE_SET_LEN,
|
||||
MSI_OSD_HARDWARE_ENCODE_GET_LEN,
|
||||
MSI_OSD_HARDWARE_ENCODE_BUF,
|
||||
MSI_OSD_HARDWARE_DEV,
|
||||
MSI_OSD_HARDWARE_STREAM_RESET,
|
||||
MSI_OSD_HARDWARE_STREAM_STOP,
|
||||
MSI_OSD_ENC_MSI_ENABLE,
|
||||
};
|
||||
|
||||
enum MSI_SCALE3_NORMAL_CMD
|
||||
{
|
||||
MSI_SCALE3_START,
|
||||
MSI_SCLAE3_NORMAL_ADD_DPI, //从scale3增加一个获取某个分辨率的yuv数据,暂定内部只有一个buf,
|
||||
//用于分时复用,考虑连拍的问题,如果采用一次性全部获取,会导致推屏丢帧严重
|
||||
|
||||
};
|
||||
|
||||
enum MSI_SCALE1_CMD
|
||||
{
|
||||
MSI_SCALE1_RESET_DPI,
|
||||
MSI_SCALE1_STOP,
|
||||
};
|
||||
|
||||
enum MSI_SCALE2_CMD
|
||||
{
|
||||
MSI_SCALE2_START,
|
||||
MSI_SCALE2_SET_FILTER_TYPE,
|
||||
};
|
||||
|
||||
enum MSI_LCD_VIDEO_CMD
|
||||
{
|
||||
MSI_VIDEO_ENABLE,
|
||||
MSI_VIDEO_GET_ENABLE,
|
||||
};
|
||||
|
||||
enum MSI_LCD_OSD_CMD
|
||||
{
|
||||
// osd使用
|
||||
MSI_OSD_ENABLE,
|
||||
};
|
||||
|
||||
enum MSI_JPEG0_CMD
|
||||
{
|
||||
MSI_JPEG_STOP,
|
||||
MSI_JPEG_RESET_FROM,
|
||||
MSI_JPEG_RESET_DPI,
|
||||
MSI_PRC_MJPEG_KICK,
|
||||
MSI_PRC_REGISTER_ISR,
|
||||
};
|
||||
|
||||
enum MSI_JPEG_CONCAT
|
||||
{
|
||||
MSI_JPEG_OPEN,
|
||||
MSI_JPEG_MSG,
|
||||
MSI_JPEG_START,
|
||||
MSI_JPEG_FROM,
|
||||
MSI_JPEG_NODE_COUNT,
|
||||
MSI_GET_JPEG_MSI,
|
||||
MSI_SET_GEN420_TYPE,
|
||||
MSI_SET_SCALE1_TYPE,
|
||||
MSI_SET_TIME,
|
||||
MSI_SET_SCALE1_AUTO_FLAG,
|
||||
};
|
||||
|
||||
enum MSI_JPEG_HARDWARE
|
||||
{
|
||||
MSI_JPEG_HARDWARE_MSG,
|
||||
MSI_JPEG_HARDWARE_START,
|
||||
MSI_JPEG_HARDWARE_STOP,
|
||||
MSI_JPEG_HARDWARE_FROM,
|
||||
MSI_JPEG_HARDWARE_SET_GEN420_TYPE,
|
||||
MSI_JPEG_HARDWARE_SET_SCALE1_TYPE,
|
||||
MSI_JPEG_SET_TIME,
|
||||
MSI_JPEG_SET_LEN,
|
||||
MSI_JPEG_SET_SCALE1_FLAG,
|
||||
};
|
||||
|
||||
enum MSI_AUTO_JPG
|
||||
{
|
||||
MSI_AUTO_JPG_SWITCH_ENCODE_SRC,
|
||||
};
|
||||
|
||||
enum MSI_AUTO_H264
|
||||
{
|
||||
MSI_AUTO_H264_MODE, //切换模式,0:默认模式 1:缩时录影模式(如果修改帧率,需要先停止再设置时间)
|
||||
MSI_AUTO_H264_TIMELAPSE_TIME, //设置缩时录影时间
|
||||
|
||||
};
|
||||
|
||||
enum MSI_JPG_RECODE
|
||||
{
|
||||
MSI_JPG_RECODE_MAGIC,
|
||||
MSI_JPG_RECODE_FORCE_TYPE
|
||||
};
|
||||
|
||||
enum MSI_JPEG_DECODE_MSG
|
||||
{
|
||||
MSI_JPEG_DECODE_X_Y,
|
||||
MSI_JPEG_DECODE_FORCE_TYPE,
|
||||
MSI_JPEG_DECODE_MAGIC,
|
||||
};
|
||||
|
||||
enum MSI_JPG_THUMB
|
||||
{
|
||||
MSI_JPG_THUMB_TAKEPHOTO,
|
||||
MSI_JPG_THUMB_TAKEPHOTO_SETPATH,
|
||||
};
|
||||
|
||||
enum MSI_DECODE_CMD
|
||||
{
|
||||
MSI_DECODE_SET_W_H,
|
||||
MSI_DECODE_SET_IN_OUT_SIZE,
|
||||
MSI_DECODE_SET_STEP,
|
||||
MSI_DECODE_READY,
|
||||
MSI_DECOE_START,
|
||||
};
|
||||
|
||||
enum MSI_PLAYER_CMD
|
||||
{
|
||||
MSI_FORWARD_INDEX,
|
||||
MSI_REWIND_INDEX,
|
||||
MSI_PLAYER_MAGIC,
|
||||
MSI_PLAYER_STATUS,
|
||||
};
|
||||
|
||||
enum MSI_MEDIA_PLAYER_CMD
|
||||
{
|
||||
MSI_MEDIA_ADD_FILE_MSI,
|
||||
MSI_MEDIA_ADD_OUTPUT,
|
||||
MSI_MEDIA_DEL_OUTPUT,
|
||||
MSI_MEDIA_PAUSE,
|
||||
MSI_MEDIA_PLAY,
|
||||
MSI_MEDIA_PLAY_1FPS,
|
||||
};
|
||||
|
||||
enum MSI_MEDIA_CTRL_CMD
|
||||
{
|
||||
MSI_MEDIA_CTRL_PLAY,
|
||||
MSI_MEDIA_CTRL_PLAY_1FPS,
|
||||
MSI_MEDIA_CTRL_RECORD_START,
|
||||
MSI_MEDIA_CTRL_EVENT_START,
|
||||
MSI_MEDIA_CTRL_EVENT_STOP,
|
||||
MSI_MEDIA_CTRL_GET_RECTIME,
|
||||
MSI_MEDIA_CTRL_SET_RECORD_SIZE,
|
||||
MSI_MEDIA_CTRL_SET_RECORD_SEC,
|
||||
};
|
||||
|
||||
enum MSI_VIDEO_DEMUX_CTRL_CMD
|
||||
{
|
||||
MSI_VIDEO_DEMUX_JMP_TIME,
|
||||
MSI_VIDEO_DEMUX_FORWARD_TIME,
|
||||
MSI_VIDEO_DEMUX_REWIND_TIME,
|
||||
MSI_VIDEO_DEMUX_SET_STATUS,
|
||||
MSI_VIDEO_DEMUX_GET_STATUS,
|
||||
MSI_VIDEO_DEMUX_START,
|
||||
MSI_VIDEO_DEMUX_STOP,
|
||||
MSI_VIDEO_DEMUX_PAUSE,
|
||||
};
|
||||
|
||||
enum MSI_TAKEPHOTO_SCALE3_CMD
|
||||
{
|
||||
MSI_TAKEPHOTO_SCALE3_KICK,
|
||||
MSI_TAKEPHOTO_SCALE3_STOP,
|
||||
};
|
||||
|
||||
enum MSI_CSC_CMD
|
||||
{
|
||||
MSI_CSC_MSI_ENABLE,
|
||||
};
|
||||
|
||||
#endif
|
||||
1038
sdk/app/algorithm/stream_frame/stream_frame.c
Normal file
1038
sdk/app/algorithm/stream_frame/stream_frame.c
Normal file
File diff suppressed because it is too large
Load Diff
189
sdk/app/algorithm/stream_frame/stream_frame.h
Normal file
189
sdk/app/algorithm/stream_frame/stream_frame.h
Normal file
@@ -0,0 +1,189 @@
|
||||
#ifndef __STREAM_FRAME_H
|
||||
#define __STREAM_FRAME_H
|
||||
#include "typesdef.h"
|
||||
#include "stream_define.h"
|
||||
//定义流的一些函数操作的回调函数,用于不同状态的时候分别通知流
|
||||
enum
|
||||
{
|
||||
STREAM_OPEN_ENTER, //准备打开流
|
||||
STREAM_OPEN_EXIT, //打开流完成退出
|
||||
STREAM_OPEN_FAIL, //打开失败
|
||||
|
||||
STREAM_CLOSE_ENTER, //准备关闭流
|
||||
STREAM_CLOSE_EXIT, //关闭流完成退出
|
||||
STREAM_CLOSE_FAIL, //打开失败
|
||||
|
||||
STREAM_DATA_DIS, //自定义内存分配(open的时候会调用)
|
||||
STREAM_DATA_DESTORY, //自定义内存释放(close的时候调用)
|
||||
STREAM_FILTER_DATA, //在发送的时候,过滤数据包
|
||||
STREAM_RECV_FILTER_DATA, //接收的时候过滤不需要播放的数据包
|
||||
STREAM_SEND_DATA_START, //准备发送数据
|
||||
STREAM_SEND_DATA_FINISH, //发送数据包完成
|
||||
STREAM_RECV_DATA_FINISH,
|
||||
STREAM_SEND_TO_DEST,
|
||||
STREAM_GET_DATA_PRIV,
|
||||
|
||||
STREAM_DATA_FREE,
|
||||
STREAM_DATA_FREE_END,
|
||||
|
||||
STREAM_SEND_CMD, //向流发送命令,可以执行一些特殊操作(如果流不想想响应,则不去响应就行了)
|
||||
STREAM_DEL,
|
||||
|
||||
|
||||
|
||||
STREAM_DEFAULT_FINISH = 0x80,//定义流默认值最大,0x81-0xff都是用户流自定义
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
STREAM_AVAILABLE, //流可用
|
||||
STREAM_ISUED, //被使用
|
||||
STREAM_UNAVAILABLE,
|
||||
STREAM_WAIT_GC_MARKER,
|
||||
STREAM_WAIT_GC_CLEAN,
|
||||
STREAM_AVAILABLE_AGAIN, //流可重复利用,这个时候可能ref不为0,但是其他资源被释放
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct data_structure;
|
||||
struct data_list;
|
||||
struct stream_list;
|
||||
typedef struct stream_s stream;
|
||||
|
||||
|
||||
typedef int (*d_free_func)(struct data_structure *d);
|
||||
typedef int (*stream_priv_func)(struct stream_s *s,void *priv,int opcode);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef void *(*stream_get_data)(void *data);
|
||||
typedef uint32_t (*stream_get_data_time)(void *data);
|
||||
typedef uint32_t (*stream_get_data_len)(void *data);
|
||||
typedef void (*stream_data_free)(void *data);
|
||||
typedef uint32 (*stream_data_custom_func)(void *data,int opcode,void *priv);
|
||||
typedef uint32 (*stream_self_cmd)(stream *s,int opcode,uint32_t arg);
|
||||
|
||||
|
||||
|
||||
typedef uint32_t (*stream_set_data_len)(void *data,uint32_t len);
|
||||
typedef uint32_t (*stream_set_data_timestamp)(void *data,uint32_t timestamp);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
//公用函数
|
||||
stream_get_data get_data; //获取data实体(不一定是数组可能是一个结构体,看流的定义)
|
||||
stream_get_data_len get_data_len; //获取data的长度
|
||||
stream_set_data_len set_data_len;
|
||||
stream_data_free free; //释放data
|
||||
stream_get_data_time get_data_time; //获取data的time
|
||||
stream_set_data_timestamp set_data_time;
|
||||
|
||||
//用户扩展的函数(可以从data获取到到stream,一般给终端调用)
|
||||
stream_data_custom_func custom_func;
|
||||
|
||||
|
||||
}stream_ops_func;
|
||||
|
||||
|
||||
//数据的结构体
|
||||
struct data_structure
|
||||
{
|
||||
void *data; //数据的空间,自己申请赋值,可以是一个结构体也可以是一个数组,流自己决定,只是接收方要明确知道该数据的格式(提前协商)
|
||||
struct data_structure *next;
|
||||
struct data_structure *prev;
|
||||
struct stream_s *s;
|
||||
//注册函数,通过参数去获取一系列参数
|
||||
stream_ops_func *ops;
|
||||
void *priv;//私有的结构体
|
||||
int type; //类型,理论每一个stream的数据类型都不是一样的
|
||||
d_free_func free; //释放函数
|
||||
int ref; //引用数量
|
||||
uint32_t timestamp;
|
||||
|
||||
};
|
||||
|
||||
struct data_list
|
||||
{
|
||||
struct data_structure *data;//数据
|
||||
struct data_list *next; //指针指向下一个
|
||||
struct data_list *prev; //指针指向下一个
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct stream_list
|
||||
{
|
||||
struct stream_list *next;
|
||||
struct stream_list *prev;
|
||||
struct stream_s *s;
|
||||
int enable; //独立一个开关,可以随时停止发送
|
||||
};
|
||||
struct stream_s
|
||||
{
|
||||
struct stream_list *s_list;
|
||||
struct stream_s *next;
|
||||
struct stream_s *prev;
|
||||
void *priv; //流自己的私有结构体
|
||||
stream_priv_func func; //流自己的操作函数,可以自定义操作
|
||||
const char *name; //stream的名称
|
||||
int used; //是否被使用
|
||||
int enable; //是否使能
|
||||
int ref; //引用次数,为0,代表没有人在使用
|
||||
int open_ref; //open成功后,会+1,close一次会-1,知道变成0后,才能实际关闭
|
||||
|
||||
//给stream发送命令(要保证stream没有被提前释放)
|
||||
stream_self_cmd self_cmd_func;
|
||||
//d_free_func free; //释放data的函数,流自己专有的,释放的时候,先调用这个,再调用默认的
|
||||
|
||||
|
||||
int src_d_list_count; //d_list的总数量,open的时候初始化好,直到删除才能被修改
|
||||
void *src_d_list_head; //记录申请的空间头,删除的时候直接free掉
|
||||
void *d_list_head; //记录申请的空间头,删除的时候直接free掉
|
||||
|
||||
//自己data的链表结构体
|
||||
struct data_structure *src_d_list_f; //当是data产生源头的时候,这里可以调用的链表数量
|
||||
struct data_structure *src_d_list_u; //如果被使用,则放在这个链表中,释放的时候是释放到src_d_list_f;
|
||||
|
||||
|
||||
//接收的data链表结构体
|
||||
struct data_list *d_list_f;//可用数据链表
|
||||
struct data_list *d_list_u;//已有数据链表
|
||||
};
|
||||
|
||||
void *open_stream(const char *name,int data_count,int recv_count,stream_priv_func func,void *priv);
|
||||
int close_stream(struct stream_s *s);
|
||||
int streamSrc_bind_streamDest(struct stream_s *s,const char *name);
|
||||
int streamSrc_unbind_streamDest(struct stream_s *s,const char *name);
|
||||
int send_data_to_stream(struct data_structure *data);
|
||||
int enable_stream(struct stream_s *s,int enable);
|
||||
struct data_structure *get_src_data_f(struct stream_s *s);
|
||||
struct data_structure *recv_real_data(struct stream_s *s);
|
||||
void *get_real_data(void *data_struct);
|
||||
int free_data(void *data_struct);
|
||||
void stream_data_mem_dis(struct stream_s *s,uint8_t *buf_head,int uint_len,int count);
|
||||
int force_del_data(struct data_structure *data);
|
||||
void stream_data_dis_mem(struct stream_s *s,int count);
|
||||
void *get_stream_real_data(struct data_structure* data);
|
||||
uint32_t get_stream_real_data_len(struct data_structure* data);
|
||||
void send_stream_cmd(struct stream_s *s,void *data);
|
||||
uint32_t set_stream_real_data_len(struct data_structure* data,uint32_t len);
|
||||
void stream_work_queue_start();
|
||||
uint32_t stream_data_custom_cmd_func(struct data_structure* data,int opcode,void *priv);
|
||||
uint32_t set_stream_data_time(struct data_structure* data,uint32_t timestamp);
|
||||
uint32_t get_stream_data_timestamp(struct data_structure* data);
|
||||
void *open_stream_available(const char *name,int data_count,int recv_count,stream_priv_func func,void *priv);
|
||||
uint32_t register_stream_self_cmd_func(stream *s,stream_self_cmd func);
|
||||
|
||||
uint32_t stream_self_cmd_func(stream *s,int opcode,uint32_t arg);
|
||||
int open_stream_again(stream *s);
|
||||
void broadcast_cmd_to_destStream(stream *s,uint32_t cmd);
|
||||
void stream_data_dis_mem_custom(stream *s);
|
||||
#endif
|
||||
268
sdk/app/app_iic/app_iic.c
Normal file
268
sdk/app/app_iic/app_iic.c
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "sys_config.h"
|
||||
#include "basic_include.h"
|
||||
#include "hal/lcdc.h"
|
||||
#include "hal/spi.h"
|
||||
#include "hal/i2c.h"
|
||||
#include "dev/lcdc/hglcdc.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "stream_frame.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list; //iic queue hand
|
||||
struct i2c_device *i2c; //iic dev
|
||||
uint32_t len;
|
||||
uint8_t *table;
|
||||
uint8_t scl_io;
|
||||
uint8_t sda_io;
|
||||
uint8_t id_addr;
|
||||
uint8_t rw_sta; //0:normal read 1:normal write 2:table write
|
||||
uint8_t sta; //0:idle 1:data ready
|
||||
uint8_t devid;
|
||||
uint8_t *trx_buff; //用户自定义的buff空间
|
||||
}iic_queue_wq;
|
||||
|
||||
|
||||
volatile struct list_head iic_queue_head;
|
||||
|
||||
static struct os_semaphore iicwq_sem = {0,NULL};
|
||||
|
||||
void iicwq_sema_init()
|
||||
{
|
||||
os_sema_init(&iicwq_sem,0);
|
||||
}
|
||||
|
||||
void iicwq_sema_down(int32 tmo_ms)
|
||||
{
|
||||
os_sema_down(&iicwq_sem,tmo_ms);
|
||||
}
|
||||
|
||||
void iicwq_sema_up()
|
||||
{
|
||||
os_sema_up(&iicwq_sem);
|
||||
}
|
||||
|
||||
int register_iic_queue(struct i2c_device *i2c,uint8_t scl_io,uint8_t sda_io,uint8_t id_addr){
|
||||
static uint8_t idnum= 1;
|
||||
iic_queue_wq *wq;
|
||||
wq = malloc(sizeof(iic_queue_wq));
|
||||
wq->scl_io = scl_io;
|
||||
wq->sda_io = sda_io;
|
||||
wq->id_addr= id_addr;
|
||||
wq->sta = 0;
|
||||
wq->i2c = i2c;
|
||||
wq->devid = idnum;
|
||||
wq->trx_buff = NULL;
|
||||
INIT_LIST_HEAD(&wq->list);
|
||||
list_add_tail(&wq->list,(struct list_head*)&iic_queue_head);
|
||||
return idnum++;
|
||||
}
|
||||
|
||||
int unregister_iic_queue(uint8_t devid){
|
||||
int ret = 0;
|
||||
struct list_head *dlist;
|
||||
|
||||
iic_queue_wq* iicdev;
|
||||
if(list_empty((struct list_head *)&iic_queue_head) != TRUE){
|
||||
dlist = (struct list_head *)&iic_queue_head;
|
||||
do{
|
||||
dlist = dlist->next;
|
||||
if(dlist == &iic_queue_head){
|
||||
return -1;
|
||||
}else{
|
||||
iicdev = list_entry((struct list_head *)dlist,iic_queue_wq,list);
|
||||
if(iicdev->devid == devid){
|
||||
list_del(&iicdev->list);
|
||||
free(iicdev);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}while(1);
|
||||
}else{
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iic_devid_set_addr(uint8_t devid,uint8_t addr){
|
||||
int ret = 0;
|
||||
struct list_head *dlist;
|
||||
iic_queue_wq* iicdev;
|
||||
if(list_empty((struct list_head *)&iic_queue_head) != TRUE){
|
||||
dlist = (struct list_head *)&iic_queue_head;
|
||||
do{
|
||||
dlist = dlist->next;
|
||||
if(dlist == &iic_queue_head){
|
||||
return -2; //no this device
|
||||
}else{
|
||||
iicdev = list_entry((struct list_head *)dlist,iic_queue_wq,list);
|
||||
if(iicdev->devid == devid){
|
||||
iicdev->id_addr= addr;
|
||||
return 1; //this id all ready finish
|
||||
}
|
||||
}
|
||||
}while(1);
|
||||
}else{
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int wake_up_iic_queue(uint8_t devid,uint8_t *table,uint32_t len,uint8_t rw_sta,uint8_t *trx_buff){
|
||||
int ret = 0;
|
||||
struct list_head *dlist;
|
||||
iic_queue_wq* iicdev;
|
||||
if(list_empty((struct list_head *)&iic_queue_head) != TRUE){
|
||||
dlist = (struct list_head *)&iic_queue_head;
|
||||
do{
|
||||
dlist = dlist->next;
|
||||
if(dlist == &iic_queue_head){
|
||||
return -1;
|
||||
}else{
|
||||
iicdev = list_entry((struct list_head *)dlist,iic_queue_wq,list);
|
||||
if(iicdev->devid == devid){
|
||||
iicdev->table = table;
|
||||
iicdev->len = len;
|
||||
if(iicdev->sta == 1){
|
||||
return 2; //this id all ready running
|
||||
}
|
||||
iicdev->sta = 1;
|
||||
iicdev->rw_sta= rw_sta;
|
||||
iicdev->trx_buff = trx_buff;
|
||||
iicwq_sema_up();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}while(1);
|
||||
}else{
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iic_devid_finish(uint8_t devid){
|
||||
int ret = 0;
|
||||
struct list_head *dlist;
|
||||
iic_queue_wq* iicdev;
|
||||
if(list_empty((struct list_head *)&iic_queue_head) != TRUE){
|
||||
dlist = (struct list_head *)&iic_queue_head;
|
||||
do{
|
||||
dlist = dlist->next;
|
||||
if(dlist == &iic_queue_head){
|
||||
return -2; //no this device
|
||||
}else{
|
||||
iicdev = list_entry((struct list_head *)dlist,iic_queue_wq,list);
|
||||
if(iicdev->devid == devid){
|
||||
if(iicdev->sta == 0){
|
||||
return 1; //this id all ready finish
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}while(1);
|
||||
}else{
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iic_run_thread(void *d){
|
||||
// int32 iic_table_finish;
|
||||
// int out_time;
|
||||
scatter_data *table_scatter_data;
|
||||
struct i2c_device *iic_dev;
|
||||
struct i2c_device *iic2_dev;
|
||||
struct list_head *dlist;
|
||||
iic_queue_wq* iicdev;
|
||||
iic_dev = (struct i2c_device *)dev_get(HG_I2C1_DEVID);
|
||||
iic2_dev = (struct i2c_device *)dev_get(HG_I2C2_DEVID);
|
||||
while(1){
|
||||
iicwq_sema_down(-1);
|
||||
if(list_empty((struct list_head *)&iic_queue_head) != TRUE){
|
||||
dlist =(struct list_head *) &iic_queue_head;
|
||||
do{
|
||||
dlist = dlist->next;
|
||||
if(dlist == &iic_queue_head){
|
||||
break;
|
||||
}else{
|
||||
iicdev = list_entry((struct list_head *)dlist,iic_queue_wq,list);
|
||||
if(iicdev->sta == 1){
|
||||
gpio_driver_strength(iicdev->scl_io, GPIO_DS_G3);
|
||||
gpio_driver_strength(iicdev->sda_io, GPIO_DS_G3);
|
||||
gpio_set_mode(iicdev->scl_io, GPIO_OPENDRAIN_PULL_UP, GPIO_PULL_LEVEL_4_7K);
|
||||
gpio_set_mode(iicdev->sda_io, GPIO_OPENDRAIN_PULL_UP, GPIO_PULL_LEVEL_4_7K);
|
||||
if(iicdev->i2c == iic_dev){
|
||||
gpio_iomap_inout(iicdev->scl_io, GPIO_IOMAP_IN_SPI1_SCK_IN, GPIO_IOMAP_OUT_SPI1_SCK_OUT);
|
||||
gpio_iomap_inout(iicdev->sda_io, GPIO_IOMAP_IN_SPI1_IO0_IN, GPIO_IOMAP_OUT_SPI1_IO0_OUT);
|
||||
|
||||
}else{
|
||||
gpio_iomap_inout(iicdev->scl_io, GPIO_IOMAP_IN_SPI2_SCK_IN, GPIO_IOMAP_OUT_SPI2_SCK_OUT);
|
||||
gpio_iomap_inout(iicdev->sda_io, GPIO_IOMAP_IN_SPI2_IO0_IN, GPIO_IOMAP_OUT_SPI2_IO0_OUT);
|
||||
}
|
||||
if(iicdev->id_addr == 0){
|
||||
i2c_ioctl(iicdev->i2c,IIC_SET_DEVICE_ADDR,iicdev->table[2]);
|
||||
}
|
||||
//printf("scl_io:%x sda_io:%x\r\n",iicdev->scl_io,iicdev->sda_io);
|
||||
if(iicdev->rw_sta == 0){
|
||||
if (iicdev->trx_buff != NULL) {
|
||||
//处理DMA地址不对齐的情况,使用外部传入的地址空间
|
||||
i2c_read(iicdev->i2c,(int8*)&iicdev->table[3],iicdev->table[0],(int8*)iicdev->trx_buff,iicdev->table[1]);
|
||||
} else {
|
||||
i2c_read(iicdev->i2c,(int8*)&iicdev->table[3],iicdev->table[0],(int8*)&iicdev->table[3+iicdev->table[0]],iicdev->table[1]);
|
||||
}
|
||||
}else if(iicdev->rw_sta == 1){
|
||||
i2c_write(iicdev->i2c, (int8*)&iicdev->table[3],iicdev->table[0], (int8*)&iicdev->table[3+iicdev->table[0]], iicdev->table[1]);
|
||||
}else if(iicdev->rw_sta == 2){
|
||||
table_scatter_data = (scatter_data*)iicdev->table;
|
||||
// out_time = 0x1ff;
|
||||
// iic_table_finish = 0;
|
||||
i2c_master_write_table(iicdev->i2c, iicdev->len, iicdev->id_addr, table_scatter_data);
|
||||
// while((iic_table_finish == 0)&&(out_time != 0)){
|
||||
// iic_table_finish = i2c_ioctl(iic_dev,IIC_GET_TX_STATUS, 0);
|
||||
// out_time--;
|
||||
// os_sleep_ms(1);
|
||||
// }
|
||||
}
|
||||
|
||||
gpio_set_dir(iicdev->scl_io, GPIO_DIR_INPUT);
|
||||
gpio_set_dir(iicdev->sda_io, GPIO_DIR_INPUT);
|
||||
gpio_iomap_input(iicdev->scl_io,GPIO_IOMAP_INPUT);
|
||||
gpio_iomap_input(iicdev->sda_io,GPIO_IOMAP_INPUT);
|
||||
iicdev->sta = 0;
|
||||
}
|
||||
}
|
||||
}while(1);
|
||||
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void iic_thread_init(){
|
||||
struct i2c_device *iic_dev;
|
||||
iic_dev = (struct i2c_device *)dev_get(HG_I2C1_DEVID);
|
||||
|
||||
struct i2c_device *iic_dev2;
|
||||
iic_dev2 = (struct i2c_device *)dev_get(HG_I2C2_DEVID);
|
||||
|
||||
i2c_open(iic_dev, IIC_MODE_MASTER, IIC_ADDR_7BIT, 0);
|
||||
i2c_set_baudrate(iic_dev,250000UL);
|
||||
i2c_ioctl(iic_dev,IIC_SDA_OUTPUT_DELAY,20);
|
||||
i2c_ioctl(iic_dev,IIC_FILTERING,20);
|
||||
i2c_ioctl(iic_dev,IIC_SET_WRITE_TABLE_MODE, 1);
|
||||
|
||||
// i2c_open(iic_dev2, IIC_MODE_MASTER, IIC_ADDR_7BIT, 0);
|
||||
// i2c_set_baudrate(iic_dev2,250000UL);
|
||||
// i2c_ioctl(iic_dev2,IIC_FILTERING,20);
|
||||
// i2c_ioctl(iic_dev2,IIC_SET_WRITE_TABLE_MODE, 1);
|
||||
|
||||
INIT_LIST_HEAD((struct list_head *)&iic_queue_head);
|
||||
iicwq_sema_init();
|
||||
os_task_create("iic_thread", iic_run_thread, NULL, OS_TASK_PRIORITY_HIGH-1, 0, NULL, 1024);
|
||||
}
|
||||
|
||||
23
sdk/app/app_iic/app_iic.h
Normal file
23
sdk/app/app_iic/app_iic.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef __APP_IIC_H
|
||||
#define __APP_IIC_H
|
||||
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "stream_frame.h"
|
||||
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "hal/i2c.h"
|
||||
|
||||
|
||||
|
||||
void iic_thread_init();
|
||||
void iic_run_thread(void *d);
|
||||
int iic_devid_finish(uint8_t devid);
|
||||
int wake_up_iic_queue(uint8_t devid,uint8_t *table,uint32_t len,uint8_t rw_sta,uint8_t *trx_buff);
|
||||
int unregister_iic_queue(uint8_t devid);
|
||||
int register_iic_queue(struct i2c_device *i2c,uint8_t scl_io,uint8_t sda_io,uint8_t id_addr);
|
||||
int iic_devid_set_addr(uint8_t devid,uint8_t addr);
|
||||
|
||||
|
||||
#endif
|
||||
626
sdk/app/app_lcd/app_lcd.c
Normal file
626
sdk/app/app_lcd/app_lcd.c
Normal file
@@ -0,0 +1,626 @@
|
||||
#include "basic_include.h"
|
||||
#include "hal/lcdc.h"
|
||||
#include "hal/spi.h"
|
||||
#include "hal/dsi.h"
|
||||
|
||||
#include "dev/lcdc/hglcdc.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "stream_frame.h"
|
||||
#include "app_lcd.h"
|
||||
#include "user_work/user_work.h"
|
||||
#ifdef PIN_FROM_PARAM
|
||||
#include "pin_param.h"
|
||||
#endif
|
||||
|
||||
#ifdef LCD_EN
|
||||
|
||||
#define LCD_ROTATE_LINE 64
|
||||
|
||||
#define OSD_EN 1
|
||||
#define LCD_SCREEN_RECORD_EN 0 // 录屏功能
|
||||
|
||||
struct app_lcd_s lcd_msg_s;
|
||||
|
||||
void lcd_hardware_init565();
|
||||
void lcd_hardware_init666();
|
||||
extern void lcd_register_read_3line(struct spi_device *spi_dev, uint32 code, uint8 *buf, uint32 len);
|
||||
extern void lcd_table_init(struct spi_device *spi_dev, uint8_t *lcd_table);
|
||||
extern void lcd_table_init_MCU(struct lcdc_device *lcd_dev, uint8_t (*lcd_table)[2]);
|
||||
extern void lcd_reg_table_init(struct lcdc_device *lcd_dev, uint8 lcd_bus_type, uint8_t *lcd_table);
|
||||
|
||||
// 暂时没有作处理
|
||||
static void lcd_timeout1(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
struct app_lcd_s *lcd_s = (struct app_lcd_s *) irq_data;
|
||||
struct lcdc_device *lcd_dev = lcd_s->lcd_dev;
|
||||
lcdc_set_timeout_info(lcd_dev, 0, 3);
|
||||
|
||||
os_printf("lcd_timeout\r\n");
|
||||
// 出现timeout,说明可能哪里卡住了,让应用层重新启动
|
||||
lcd_s->hardware_ready = 1;
|
||||
lcd_s->rekick_lcd = 1;
|
||||
}
|
||||
|
||||
// 暂时没有作处理
|
||||
static void lcd_te_isr1(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
os_printf("%s:%d\n", __FUNCTION__, __LINE__);
|
||||
struct app_lcd_s *lcd_s = (struct app_lcd_s *) irq_data;
|
||||
struct lcdc_device *lcd_dev;
|
||||
lcd_dev = lcd_s->lcd_dev;
|
||||
os_printf("--------------------------------------------te------------------"
|
||||
"---------------\r\n");
|
||||
}
|
||||
|
||||
static void lcd_squralbuf_done1(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
struct app_lcd_s *lcd_s = (struct app_lcd_s *) irq_data;
|
||||
// 理论这里只是唤醒信号量之类,由线程来决定是否继续显示
|
||||
// os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
#if LCD_SCREEN_RECORD_EN
|
||||
static uint32 lcd_num = 0;
|
||||
static uint32 dither = 0;
|
||||
if ((lcd_num % 200) == 0)
|
||||
{
|
||||
os_printf("---------------------------------------------------------\r\n");
|
||||
if (dither == 1)
|
||||
{
|
||||
lcdc_dither_en(lcd_s->lcd_dev, 0);
|
||||
lcdc_screen_start(lcd_s->lcd_dev, 1);
|
||||
dither = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lcdc_dither_en(lcd_s->lcd_dev, 1);
|
||||
lcdc_screen_start(lcd_s->lcd_dev, 1);
|
||||
dither = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
lcd_s->end_time = os_jiffies();
|
||||
lcd_s->refresh_time = lcd_s->end_time - lcd_s->start_time;
|
||||
if (lcd_s->hardware_auto_ks)
|
||||
{
|
||||
lcd_s->hardware_ready = 0;
|
||||
// 判断是否启动了硬件自动kick
|
||||
if (!lcd_s->get_auto_ks)
|
||||
{
|
||||
// 启动自动kick
|
||||
lcd_s->get_auto_ks = 1;
|
||||
lcdc_video_enable_auto_ks(lcd_s->lcd_dev, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lcd_s->get_auto_ks)
|
||||
{
|
||||
lcd_s->get_auto_ks = 0;
|
||||
lcdc_video_enable_auto_ks(lcd_s->lcd_dev, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd_s->hardware_ready = 1;
|
||||
}
|
||||
}
|
||||
lcd_s->app_lcd_cb(lcd_s);
|
||||
|
||||
#if 1
|
||||
uint32_t st0, st1;
|
||||
struct dsi_device *dsi_dev;
|
||||
dsi_dev = lcd_s->lcd_dsi_dev; //(struct dsi_device *)dev_get(HG_DSI_DEVID);
|
||||
st0 = mipi_dsi_get_sta0(dsi_dev);
|
||||
st1 = mipi_dsi_get_sta1(dsi_dev);
|
||||
if ((st0 != 0) || (st1 != 0))
|
||||
{
|
||||
os_printf("L(%08x %08x)\r\n", st0, st1);
|
||||
mipi_dsi_reset_module(dsi_dev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LCD_SCREEN_RECORD_EN
|
||||
static void lcd_screen_finish(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
os_printf("%s %d\r\n", __func__, __LINE__);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t g_read_hardware_auto_ks()
|
||||
{
|
||||
// os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
return lcd_msg_s.get_auto_ks;
|
||||
}
|
||||
|
||||
uint8_t g_set_hardware_auto_ks(uint8_t en)
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t timeout = 0;
|
||||
if (en)
|
||||
{
|
||||
lcd_msg_s.hardware_auto_ks = en;
|
||||
while (!lcd_msg_s.get_auto_ks && (timeout < 100))
|
||||
{
|
||||
timeout++;
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flags = disable_irq();
|
||||
lcd_msg_s.hardware_auto_ks = en;
|
||||
enable_irq(flags);
|
||||
}
|
||||
|
||||
return lcd_msg_s.get_auto_ks;
|
||||
}
|
||||
|
||||
// 返回的是osd旋转和w h
|
||||
static void get_osd_w_h(uint16_t *w, uint16_t *h, uint8_t *rotate)
|
||||
{
|
||||
*w = lcdstruct.osd_w;
|
||||
*h = lcdstruct.osd_h;
|
||||
*rotate = lcdstruct.osd_scan_mode;
|
||||
}
|
||||
|
||||
static void get_video_w_h(uint16_t *video_w, uint16_t *video_h)
|
||||
{
|
||||
*video_w = lcdstruct.video_w;
|
||||
*video_h = lcdstruct.video_h;
|
||||
}
|
||||
|
||||
// 返回屏幕的size和旋转角度
|
||||
static void get_screen_w_h(uint16_t *screen_w, uint16_t *screen_h, uint8_t *video_rotate)
|
||||
{
|
||||
*screen_w = lcdstruct.screen_w;
|
||||
*screen_h = lcdstruct.screen_h;
|
||||
*video_rotate = lcdstruct.scan_mode;
|
||||
}
|
||||
|
||||
// 注意,这部分不同屏以及硬件设计不一样,需要修改
|
||||
void lcd_hardware_init(uint16_t *w, uint16_t *h, uint8_t *rotate, uint16_t *screen_w, uint16_t *screen_h, uint16_t *video_w, uint16_t *video_h, uint8_t *video_rotate)
|
||||
{
|
||||
if (lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
if (lcdstruct.color_mode == LCD_MODE_666)
|
||||
{
|
||||
lcd_hardware_init666();
|
||||
}
|
||||
else if (lcdstruct.color_mode == LCD_MODE_565)
|
||||
{
|
||||
lcd_hardware_init565();
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd_hardware_init565();
|
||||
}
|
||||
}
|
||||
else if ((lcdstruct.lcd_bus_type == LCD_BUS_RGB) || (lcdstruct.lcd_bus_type == LCD_BUS_SPI4))
|
||||
{
|
||||
lcd_hardware_init565();
|
||||
}
|
||||
else if (lcdstruct.lcd_bus_type == LCD_BUS_MIPI)
|
||||
{
|
||||
lcd_hardware_init565();
|
||||
}
|
||||
|
||||
// 返回osd的w和h
|
||||
get_osd_w_h(w, h, rotate);
|
||||
get_screen_w_h(screen_w, screen_h, video_rotate);
|
||||
get_video_w_h(video_w, video_h);
|
||||
}
|
||||
|
||||
// 主要硬件初始化,但由于存在rgb屏,还是会有部分寄存器需要配置
|
||||
void lcd_hardware_init565()
|
||||
{
|
||||
uint8 pixel_dot_num = 1;
|
||||
struct lcdc_device *lcd_dev;
|
||||
struct spi_device *spi_dev;
|
||||
// uint32_t rbuf[4];
|
||||
// uint8_t *pt8;
|
||||
lcd_dev = (struct lcdc_device *) dev_get(HG_LCDC_DEVID);
|
||||
spi_dev = (struct spi_device *) dev_get(HG_SPI0_DEVID);
|
||||
|
||||
uint8_t rst = MACRO_PIN(PIN_LCD_RESET);
|
||||
|
||||
if (rst != 255)
|
||||
{
|
||||
gpio_iomap_output(rst, GPIO_IOMAP_OUTPUT);
|
||||
gpio_set_val(rst, 0);
|
||||
os_sleep_ms(100);
|
||||
gpio_set_val(rst, 1);
|
||||
os_sleep_ms(100);
|
||||
}
|
||||
|
||||
if (lcdstruct.lcd_bus_type == LCD_BUS_RGB)
|
||||
{
|
||||
|
||||
uint8 spi_buf[10];
|
||||
if (lcdstruct.init_table != NULL)
|
||||
{
|
||||
spi_open(spi_dev, 1000000, SPI_MASTER_MODE, SPI_WIRE_SINGLE_MODE, SPI_CPOL_1_CPHA_1);
|
||||
spi_ioctl(spi_dev, SPI_SET_FRAME_SIZE, 9, 0);
|
||||
// lcd spi_cfg
|
||||
_os_printf("read lcd id(%x)\r\n", (unsigned int) spi_dev);
|
||||
lcd_register_read_3line(spi_dev, 0xda, spi_buf, 4);
|
||||
_os_printf("***ID:%02x %02x %02x %02x\r\n", spi_buf[0], spi_buf[1], spi_buf[2], spi_buf[3]);
|
||||
|
||||
lcd_table_init(spi_dev, (uint8_t *) lcdstruct.init_table);
|
||||
gpio_set_val(PIN_SPI0_CS, 1);
|
||||
gpio_iomap_output(PIN_SPI0_CS, GPIO_IOMAP_OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
// scale_to_lcd_config();
|
||||
lcdc_init(lcd_dev);
|
||||
if ((lcdstruct.lcd_bus_type == LCD_BUS_I80) || (lcdstruct.lcd_bus_type == LCD_BUS_SPI4))
|
||||
{
|
||||
lcdc_open(lcd_dev);
|
||||
}
|
||||
lcdc_set_color_mode(lcd_dev, lcdstruct.color_mode);
|
||||
lcdc_set_bus_width(lcd_dev, lcdstruct.bus_width);
|
||||
lcdc_set_interface(lcd_dev, lcdstruct.lcd_bus_type);
|
||||
lcdc_set_colrarray(lcd_dev, lcdstruct.colrarray);
|
||||
pixel_dot_num = lcdstruct.color_mode / lcdstruct.bus_width;
|
||||
lcdc_set_lcd_vaild_size(lcd_dev, lcdstruct.screen_w + lcdstruct.hlw + lcdstruct.hbp + lcdstruct.hfp, lcdstruct.screen_h + lcdstruct.vlw + lcdstruct.vbp + lcdstruct.vfp, pixel_dot_num);
|
||||
lcdc_set_lcd_visible_size(lcd_dev, lcdstruct.screen_w, lcdstruct.screen_h, pixel_dot_num);
|
||||
if (lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
lcdc_mcu_signal_config(lcd_dev, lcdstruct.signal_config.value);
|
||||
}
|
||||
else if ((lcdstruct.lcd_bus_type == LCD_BUS_RGB) || (lcdstruct.lcd_bus_type == LCD_BUS_MIPI) || (lcdstruct.lcd_bus_type == LCD_BUS_QSPI))
|
||||
{
|
||||
lcdc_signal_config(lcd_dev, lcdstruct.vs_en, lcdstruct.hs_en, lcdstruct.de_en, lcdstruct.vs_inv, lcdstruct.hs_inv, lcdstruct.de_inv, lcdstruct.pclk_inv);
|
||||
lcdc_set_invalid_line(lcd_dev, lcdstruct.vlw);
|
||||
lcdc_set_valid_dot(lcd_dev, lcdstruct.hlw + lcdstruct.hbp, lcdstruct.vlw + lcdstruct.vbp);
|
||||
lcdc_set_hlw_vlw(lcd_dev, lcdstruct.hlw, 0);
|
||||
}
|
||||
lcdc_set_baudrate(lcd_dev, lcdstruct.pclk);
|
||||
lcdc_set_bigendian(lcd_dev, 1);
|
||||
if (lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
// lcd_table_init_MCU(lcd_dev, lcdstruct.init_table);
|
||||
lcd_reg_table_init(lcd_dev, lcdstruct.lcd_bus_type, (uint8_t *) (lcdstruct.init_table));
|
||||
}
|
||||
else if (lcdstruct.lcd_bus_type == LCD_BUS_MIPI)
|
||||
{
|
||||
mipi_dsi_init(lcdstruct.screen_w, lcdstruct.screen_h, lcdstruct.pclk, lcdstruct.vlw, lcdstruct.vbp, lcdstruct.vfp, lcdstruct.hlw, lcdstruct.hbp, lcdstruct.hfp, lcdstruct.lane_num,
|
||||
lcdstruct.color_mode);
|
||||
}
|
||||
else if (lcdstruct.lcd_bus_type == LCD_BUS_SPI4)
|
||||
{
|
||||
lcdc_spi_cs_lock_time(lcd_dev, 0x20, 0x20, 0x20);
|
||||
lcdc_cmd_auto_send(lcd_dev, 0, 0);
|
||||
|
||||
// pt8 = (uint8_t *)rbuf;
|
||||
// pt8[0] = 1;
|
||||
// pt8[1] = 4;
|
||||
// pt8[2] = 0x04;
|
||||
// lcdc_reg_read_data(lcd_dev,1,4,rbuf);
|
||||
// os_printf("ID:%02x %02x %02x %02x %02x %02x %02x\r\n",pt8[0],pt8[1],pt8[2],pt8[3],pt8[4],pt8[5],pt8[6]);
|
||||
lcd_reg_table_init(lcd_dev, lcdstruct.lcd_bus_type, (uint8_t *) (lcdstruct.init_table));
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_hardware_init666()
|
||||
{
|
||||
uint8 pixel_dot_num = 1;
|
||||
struct lcdc_device *lcd_dev;
|
||||
struct spi_device *spi_dev;
|
||||
|
||||
lcd_dev = (struct lcdc_device *) dev_get(HG_LCDC_DEVID);
|
||||
spi_dev = (struct spi_device *) dev_get(HG_SPI0_DEVID);
|
||||
|
||||
uint8_t rst = MACRO_PIN(PIN_LCD_RESET);
|
||||
|
||||
if (rst != 255)
|
||||
{
|
||||
gpio_iomap_output(rst, GPIO_IOMAP_OUTPUT);
|
||||
gpio_set_val(rst, 0);
|
||||
os_sleep_ms(100);
|
||||
gpio_set_val(rst, 1);
|
||||
os_sleep_ms(100);
|
||||
}
|
||||
if (lcdstruct.lcd_bus_type == LCD_BUS_RGB)
|
||||
{
|
||||
|
||||
uint8 spi_buf[10];
|
||||
if (lcdstruct.init_table != NULL)
|
||||
{
|
||||
spi_open(spi_dev, 1000000, SPI_MASTER_MODE, SPI_WIRE_SINGLE_MODE, SPI_CPOL_1_CPHA_1);
|
||||
spi_ioctl(spi_dev, SPI_SET_FRAME_SIZE, 9, 0);
|
||||
// lcd spi_cfg
|
||||
_os_printf("read lcd id(%x)\r\n", (unsigned int) spi_dev);
|
||||
lcd_register_read_3line(spi_dev, 0xda, spi_buf, 4);
|
||||
_os_printf("***ID:%02x %02x %02x %02x\r\n", spi_buf[0], spi_buf[1], spi_buf[2], spi_buf[3]);
|
||||
|
||||
lcd_table_init(spi_dev, (uint8_t *) lcdstruct.init_table);
|
||||
gpio_set_val(PIN_SPI0_CS, 1);
|
||||
gpio_iomap_output(PIN_SPI0_CS, GPIO_IOMAP_OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
// scale_to_lcd_config();
|
||||
lcdc_init(lcd_dev);
|
||||
if (lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
lcdc_open(lcd_dev);
|
||||
}
|
||||
lcdc_set_color_mode(lcd_dev, lcdstruct.color_mode);
|
||||
lcdc_set_bus_width(lcd_dev, lcdstruct.bus_width);
|
||||
lcdc_set_interface(lcd_dev, lcdstruct.lcd_bus_type);
|
||||
lcdc_set_colrarray(lcd_dev, lcdstruct.colrarray);
|
||||
pixel_dot_num = lcdstruct.color_mode / lcdstruct.bus_width;
|
||||
lcdc_set_lcd_vaild_size(lcd_dev, lcdstruct.screen_w + lcdstruct.hlw + lcdstruct.hbp + lcdstruct.hfp, lcdstruct.screen_h + lcdstruct.vlw + lcdstruct.vbp + lcdstruct.vfp, pixel_dot_num);
|
||||
lcdc_set_lcd_visible_size(lcd_dev, lcdstruct.screen_w, lcdstruct.screen_h, 3);
|
||||
if (lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
lcdc_mcu_signal_config(lcd_dev, lcdstruct.signal_config.value);
|
||||
}
|
||||
else if (lcdstruct.lcd_bus_type == LCD_BUS_RGB)
|
||||
{
|
||||
lcdc_signal_config(lcd_dev, lcdstruct.vs_en, lcdstruct.hs_en, lcdstruct.de_en, lcdstruct.vs_inv, lcdstruct.hs_inv, lcdstruct.de_inv, lcdstruct.pclk_inv);
|
||||
lcdc_set_invalid_line(lcd_dev, lcdstruct.vlw);
|
||||
lcdc_set_valid_dot(lcd_dev, lcdstruct.hlw + lcdstruct.hbp, lcdstruct.vlw + lcdstruct.vbp);
|
||||
lcdc_set_hlw_vlw(lcd_dev, lcdstruct.hlw, 0);
|
||||
}
|
||||
lcdc_set_baudrate(lcd_dev, lcdstruct.pclk);
|
||||
lcdc_set_bigendian(lcd_dev, 1);
|
||||
if (lcdstruct.lcd_bus_type == LCD_BUS_I80)
|
||||
{
|
||||
lcd_table_init_MCU(lcd_dev, lcdstruct.init_table);
|
||||
}
|
||||
|
||||
// gamma表之类没有配置,这个考虑是放在其他地方,这个函数专注硬件的初始化好了
|
||||
|
||||
#if 0
|
||||
lcdc_video_enable_gamma(lcd_dev, 1);
|
||||
lcdc_video_enable_ccm(lcd_dev, 1);
|
||||
lcdc_video_enable_constarast(lcd_dev, 1);
|
||||
lcdc_video_set_CCM_COEF0(lcd_dev, 0x00df0100);
|
||||
lcdc_video_set_CCM_COEF1(lcd_dev, 0x0003b3f3);
|
||||
lcdc_video_set_CCM_COEF2(lcd_dev, 0x0df0000d);
|
||||
lcdc_video_set_CCM_COEF3(lcd_dev, 0x00000000);
|
||||
lcdc_video_set_constarast_val(lcd_dev, 0x12);
|
||||
lcdc_video_set_gamma_R(lcd_dev, (uint32_t)rgb_gamma_table);
|
||||
lcdc_video_set_gamma_G(lcd_dev, (uint32_t)rgb_gamma_table);
|
||||
lcdc_video_set_gamma_B(lcd_dev, (uint32_t)rgb_gamma_table);
|
||||
#endif
|
||||
|
||||
lcdc_set_bus_width(lcd_dev, LCD_BUS_WIDTH_6);
|
||||
}
|
||||
|
||||
// lcd相关参数配置,w、h、rotate
|
||||
void lcd_arg_setting(uint16_t w, uint16_t h, uint8_t rotate, uint16_t screen_w, uint16_t screen_h, uint16_t video_w, uint16_t video_h, uint8_t video_rotate)
|
||||
{
|
||||
struct app_lcd_s *lcd_s = &lcd_msg_s;
|
||||
lcd_s->w = w;
|
||||
lcd_s->h = h;
|
||||
lcd_s->rotate = rotate;
|
||||
lcd_s->screen_w = screen_w;
|
||||
lcd_s->screen_h = screen_h;
|
||||
lcd_s->video_w = video_w;
|
||||
lcd_s->video_h = video_h;
|
||||
lcd_s->video_rotate = video_rotate;
|
||||
}
|
||||
|
||||
// 芯片lcd的驱动初始化
|
||||
void lcd_driver_init(const char *osd_encode_name, const char *lcd_osd_name, const char *lcd_video_p0, const char *lcd_video_p1)
|
||||
{
|
||||
struct app_lcd_s *lcd_s = &lcd_msg_s;
|
||||
struct dsi_device *dsi_dev;
|
||||
dsi_dev = (struct dsi_device *) dev_get(HG_DSI_DEVID);
|
||||
dev_put((struct dev_obj *) dsi_dev);
|
||||
lcd_s->osd_enc_msi = osd_encode_msi_init(osd_encode_name);
|
||||
|
||||
// 对应的rb初始化
|
||||
RB_INIT(&lcd_s->osd_rb, LCD_RB_COUNT);
|
||||
RB_INIT(&lcd_s->p0_rb, LCD_RB_COUNT);
|
||||
RB_INIT(&lcd_s->p1_rb, LCD_RB_COUNT);
|
||||
RB_INIT(&lcd_s->p2_rb, LCD_RB_COUNT);
|
||||
|
||||
RB_INIT(&lcd_s->delete_rb, LCD_DELETE_RB_COUNT);
|
||||
#if 1
|
||||
lcd_s->lcd_osd_msi = lcd_osd_msi(lcd_osd_name);
|
||||
lcd_s->video_p0_msi = lcd_video_msi_init(lcd_video_p0, FSTYPE_YUV_P0);
|
||||
lcd_s->video_p1_msi = lcd_video_msi_init(lcd_video_p1, FSTYPE_YUV_P1);
|
||||
lcd_s->csc_video_p2_msi = lcd_video_msi_init(R_CSC_VIDEO_P2, FSTYPE_YUV_P0);
|
||||
#endif
|
||||
|
||||
lcd_s->hardware_ready = 1;
|
||||
lcd_s->thread_exit = 0;
|
||||
lcd_s->hardware_auto_ks = 0;
|
||||
lcd_s->get_auto_ks = 0;
|
||||
|
||||
struct lcdc_device *lcd_dev;
|
||||
|
||||
lcd_dev = (struct lcdc_device *) dev_get(HG_LCDC_DEVID);
|
||||
dev_put((struct dev_obj *) lcd_dev);
|
||||
lcd_s->lcd_dev = lcd_dev;
|
||||
lcd_s->lcd_dsi_dev = dsi_dev;
|
||||
|
||||
lcdc_set_video_size(lcd_dev, lcdstruct.video_w, lcdstruct.video_h);
|
||||
|
||||
lcdc_set_rotate_p0_up(lcd_dev, 0);
|
||||
lcdc_set_rotate_p0p1_start_location(lcd_dev, 0, 0, 0, 0);
|
||||
|
||||
lcdc_set_rotate_linebuf_num(lcd_dev, LCD_ROTATE_LINE);
|
||||
lcd_s->line_buf_num = LCD_ROTATE_LINE;
|
||||
lcdc_set_video_data_from(lcd_dev, VIDEO_FROM_MEMORY_ROTATE);
|
||||
|
||||
lcdc_set_video_start_location(lcd_dev, lcdstruct.video_x, lcdstruct.video_y);
|
||||
lcdc_set_video_en(lcd_dev, 0);
|
||||
|
||||
// 设置默认值,因为这个一定要配置,并且地址与p1的地址范围要一样(就是全部是psram或者全部是sram,所以这里最好都是设置psram)
|
||||
lcdc_set_p0_rotate_y_src_addr(lcd_dev, (uint32) 0x28000000);
|
||||
lcdc_set_p0_rotate_u_src_addr(lcd_dev, (uint32) 0x28000000);
|
||||
lcdc_set_p0_rotate_v_src_addr(lcd_dev, (uint32) 0x28000000);
|
||||
|
||||
lcdc_set_osd_start_location(lcd_dev, lcdstruct.osd_x, lcdstruct.osd_y);
|
||||
lcdc_set_osd_size(lcd_dev, lcdstruct.osd_w, lcdstruct.osd_h);
|
||||
lcdc_set_osd_format(lcd_dev, OSD_RGB_565);
|
||||
// 仅仅测试新框架
|
||||
// lcdc_set_osd_dma_addr(lcd_dev,(uint32)osd565_encode_test);
|
||||
|
||||
lcdc_set_osd_alpha(lcd_dev, 0x100);
|
||||
lcdc_set_osd_enc_cfg(lcd_dev, 0xFFFFFF, 0x000000);
|
||||
lcdc_osd_spec_color_alpha(lcd_dev, 0, 0xffffff, 0x00);
|
||||
lcdc_osd_enc_en(lcd_dev, 1);
|
||||
lcdc_set_osd_en(lcd_dev, 0);
|
||||
lcdc_osd_trans_en(lcd_dev, 1);
|
||||
|
||||
lcdc_video_enable_auto_ks(lcd_dev, 0);
|
||||
lcdc_set_timeout_info(lcd_dev, 1, 3);
|
||||
|
||||
lcdc_request_irq(lcd_dev, LCD_DONE_IRQ, (lcdc_irq_hdl) &lcd_squralbuf_done1, (uint32) lcd_s);
|
||||
#if LCD_SCREEN_RECORD_EN
|
||||
uint8_t *video_psram_screen = (uint8_t *) av_psram_zalloc(SCALE_CONFIG_W * SCALE_HIGH + SCALE_CONFIG_W * SCALE_HIGH / 2);
|
||||
os_printf("LCD_SCREEN_RECORD_EN psram addr:%x\n", video_psram_screen);
|
||||
lcdc_screen_yuv_addr(lcd_dev, video_psram_screen, video_psram_screen + SCALE_CONFIG_W * SCALE_HIGH, video_psram_screen + SCALE_CONFIG_W * SCALE_HIGH + SCALE_CONFIG_W * SCALE_HIGH / 4);
|
||||
lcdc_request_irq(lcd_dev, SCREEN_DONE_IRQ, (lcdc_irq_hdl) &lcd_screen_finish, (uint32) lcd_s);
|
||||
#endif
|
||||
// lcdc_request_irq(lcd_dev, OSD_EN_IRQ, (lcdc_irq_hdl)&lcd_osd_isr1_msi, (uint32)lcd_s);
|
||||
lcdc_request_irq(lcd_dev, TIMEOUT_IRQ, (lcdc_irq_hdl) &lcd_timeout1, (uint32) lcd_s);
|
||||
if (MACRO_PIN(LCD_TE) != 255)
|
||||
{
|
||||
lcdc_te_edge_cfg(lcd_dev, 1);
|
||||
lcdc_request_irq(lcd_dev, LCD_TE_IRQ, (lcdc_irq_hdl) &lcd_te_isr1, (uint32) lcd_s);
|
||||
}
|
||||
lcdc_open(lcd_dev);
|
||||
|
||||
#if 0
|
||||
//extern void lcd_thread(void *d);
|
||||
//lcd_s->thread_hdl = os_task_create("lcd_thread", lcd_thread2, lcd_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||||
#else
|
||||
extern int32 lcd_msi_work(struct os_work * work);
|
||||
extern void lcd_msi_irq_callback(void *data);
|
||||
lcd_s->app_lcd_cb = lcd_msi_irq_callback;
|
||||
OS_WORK_INIT(&lcd_s->work, lcd_msi_work, 0);
|
||||
os_run_work_delay(&lcd_s->work, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wait_lcd_exit()
|
||||
{
|
||||
struct app_lcd_s *lcd_s = &lcd_msg_s;
|
||||
lcd_s->thread_exit = 1;
|
||||
while (lcd_s->thread_hdl)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 重复初始化,一般用于意外断电或者说休眠起来后使用
|
||||
void lcd_driver_reinit()
|
||||
{
|
||||
#if 0
|
||||
struct app_lcd_s *lcd_s = &lcd_msg_s;
|
||||
lcd_s->hardware_ready = 1;
|
||||
lcd_s->thread_exit = 0;
|
||||
lcd_s->hardware_auto_ks = 0;
|
||||
lcd_s->get_auto_ks = 0;
|
||||
struct lcdc_device *lcd_dev;
|
||||
|
||||
lcd_dev = (struct lcdc_device *)dev_get(HG_LCDC_DEVID);
|
||||
|
||||
lcd_s->lcd_dev = lcd_dev;
|
||||
|
||||
lcdc_set_video_size(lcd_dev, lcdstruct.video_w, lcdstruct.video_h);
|
||||
|
||||
// VIDEO
|
||||
lcdc_set_rotate_p0_up(lcd_dev, 0);
|
||||
lcdc_set_rotate_p0p1_start_location(lcd_dev, 0, 0, 0, 0);
|
||||
// line_buf后续再分配
|
||||
lcdc_set_rotate_linebuf_num(lcd_dev, LCD_ROTATE_LINE);
|
||||
lcdc_set_video_data_from(lcd_dev, VIDEO_FROM_MEMORY_ROTATE);
|
||||
lcdc_set_video_start_location(lcd_dev, lcdstruct.video_x, lcdstruct.video_y);
|
||||
lcdc_set_video_en(lcd_dev, 0);
|
||||
|
||||
// 设置默认值,因为这个一定要配置,并且地址与p1的地址范围要一样(就是全部是psram或者全部是sram,所以这里最好都是设置psram)
|
||||
lcdc_set_p0_rotate_y_src_addr(lcd_dev, (uint32)0x38000000);
|
||||
lcdc_set_p0_rotate_u_src_addr(lcd_dev, (uint32)0x38000000);
|
||||
lcdc_set_p0_rotate_v_src_addr(lcd_dev, (uint32)0x38000000);
|
||||
|
||||
// OSD
|
||||
lcdc_set_osd_start_location(lcd_dev, lcdstruct.osd_x, lcdstruct.osd_y);
|
||||
lcdc_set_osd_size(lcd_dev, lcdstruct.osd_w, lcdstruct.osd_h);
|
||||
lcdc_set_osd_format(lcd_dev, OSD_RGB_565);
|
||||
lcdc_set_osd_alpha(lcd_dev, 0x100);
|
||||
lcdc_set_osd_enc_head(lcd_dev, 0xFFFFFF, 0xFFFBFF);
|
||||
lcdc_set_osd_enc_diap(lcd_dev, 0x000000, 0x000000);
|
||||
lcdc_set_osd_en(lcd_dev, 0);
|
||||
|
||||
lcdc_video_enable_auto_ks(lcd_dev, 0);
|
||||
lcdc_set_timeout_info(lcd_dev, 1, 3);
|
||||
|
||||
lcdc_request_irq(lcd_dev, LCD_DONE_IRQ, (lcdc_irq_hdl)&lcd_squralbuf_done1, (uint32)lcd_s);
|
||||
|
||||
lcdc_request_irq(lcd_dev, OSD_EN_IRQ, (lcdc_irq_hdl)&lcd_osd_isr1_msi, (uint32)lcd_s);
|
||||
lcdc_request_irq(lcd_dev, TIMEOUT_IRQ, (lcdc_irq_hdl)&lcd_timeout1, (uint32)lcd_s);
|
||||
if (MACRO_PIN(LCD_TE) != 255) {
|
||||
lcdc_set_te_edge(lcd_dev, 1);
|
||||
lcdc_request_irq(lcd_dev, LCD_TE_IRQ, (lcdc_irq_hdl)&lcd_te_isr1, (uint32)lcd_s);
|
||||
}
|
||||
lcdc_open(lcd_dev);
|
||||
// lcdc_set_start_run(lcd_dev);
|
||||
|
||||
extern void lcd_thread(void *d);
|
||||
lcd_s->thread_hdl = os_task_create("lcd_thread", lcd_thread, (void *)lcd_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
void lcd_module_run2(){
|
||||
uint32_t rbuf[4];
|
||||
uint8_t *pt8;
|
||||
uint8 pixel_dot_num = 1;
|
||||
uint32_t *osd_sram_fifo;
|
||||
struct lcdc_device *lcd_dev;
|
||||
struct spi_device *spi_dev;
|
||||
struct scale_device *scale_dev;
|
||||
struct vpp_device *vpp_dev;
|
||||
struct jpg_device *jpg_dev;
|
||||
jpg_dev = (struct jpg_device *)dev_get(HG_JPG1_DEVID);
|
||||
vpp_dev = (struct vpp_device *)dev_get(HG_VPP_DEVID);
|
||||
scale_dev = (struct scale_device *)dev_get(HG_SCALE2_DEVID);
|
||||
lcd_dev = (struct lcdc_device *)dev_get(HG_LCDC_DEVID);
|
||||
spi_dev = (struct spi_device * )dev_get(HG_SPI0_DEVID);
|
||||
|
||||
lcdc_set_video_size(lcd_dev,lcdstruct.video_w,lcdstruct.video_h);
|
||||
|
||||
|
||||
|
||||
lcdc_set_osd_start_location(lcd_dev,lcdstruct.osd_x,lcdstruct.osd_y);
|
||||
|
||||
lcdc_set_osd_size(lcd_dev,lcdstruct.osd_w,lcdstruct.osd_h);
|
||||
lcdc_set_osd_dma_addr(lcd_dev,(uint32)osd565_encode_test);
|
||||
lcdc_set_osd_format(lcd_dev,OSD_RGB_565);
|
||||
|
||||
lcdc_set_osd_alpha(lcd_dev,0x100);
|
||||
lcdc_set_osd_enc_cfg(lcd_dev,0xFFFFFF,0x000000);
|
||||
lcdc_osd_spec_color_alpha(lcd_dev,0,0xffffff,0x00);
|
||||
lcdc_osd_enc_en(lcd_dev,1);
|
||||
lcdc_set_osd_en(lcd_dev,1);
|
||||
lcdc_osd_trans_en(lcd_dev,1);
|
||||
|
||||
|
||||
if((lcdstruct.lcd_bus_type == LCD_BUS_RGB)||(lcdstruct.lcd_bus_type == LCD_BUS_MIPI)||(lcdstruct.lcd_bus_type == LCD_BUS_QSPI)){
|
||||
lcdc_clock_alway_on(lcd_dev,1);
|
||||
}
|
||||
lcdc_rot_burst_dw16(lcd_dev,0);
|
||||
|
||||
lcdc_video_enable_auto_ks(lcd_dev,0);
|
||||
lcdc_set_timeout_info(lcd_dev,1,3);
|
||||
|
||||
lcdc_request_irq(lcd_dev,LCD_DONE_IRQ,(lcdc_irq_hdl )&lcd_squralbuf_done1,(uint32)lcd_dev);
|
||||
|
||||
|
||||
lcdc_open(lcd_dev);
|
||||
os_sleep_ms(10);
|
||||
lcdc_set_start_run(lcd_dev);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
117
sdk/app/app_lcd/app_lcd.h
Normal file
117
sdk/app/app_lcd/app_lcd.h
Normal file
@@ -0,0 +1,117 @@
|
||||
#ifndef __APP_LCD_H
|
||||
#define __APP_LCD_H
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "stream_frame.h"
|
||||
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
|
||||
typedef void (*app_lcd_callback)(void *lcd_s);
|
||||
#define LCD_RB_COUNT 4
|
||||
#define LCD_DELETE_RB_COUNT 8
|
||||
|
||||
struct app_lcd_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *osd_enc_msi;
|
||||
struct msi *lcd_osd_msi;
|
||||
struct msi *video_p0_msi;
|
||||
struct msi *video_p1_msi;
|
||||
struct msi *csc_video_p2_msi;
|
||||
|
||||
//创建多个队列,分别是osd、p0、p1以及csc_p2(将收到的fb放到队列,然后中断去获取队列,这里采用ringbuf的形式)
|
||||
RBUFFER_DEF(osd_rb, struct framebuff *, LCD_RB_COUNT);
|
||||
RBUFFER_DEF(p0_rb, struct framebuff *, LCD_RB_COUNT);
|
||||
RBUFFER_DEF(p1_rb, struct framebuff *, LCD_RB_COUNT);
|
||||
RBUFFER_DEF(p2_rb, struct framebuff *, LCD_RB_COUNT);
|
||||
|
||||
RBUFFER_DEF(delete_rb, struct framebuff *, LCD_DELETE_RB_COUNT);
|
||||
|
||||
struct framebuff * p0_fb;
|
||||
struct framebuff * p1_fb;
|
||||
struct framebuff * p2_fb;
|
||||
struct framebuff * osd_fb;
|
||||
|
||||
app_lcd_callback app_lcd_cb;
|
||||
|
||||
struct lcdc_device *lcd_dev;
|
||||
struct dsi_device *lcd_dsi_dev;
|
||||
// 只有thread_hdl退出后,才可以休眠
|
||||
void *thread_hdl;
|
||||
void *line_buf;
|
||||
void *free_line_buf;
|
||||
uint32_t start_time;
|
||||
uint32_t end_time;
|
||||
uint32_t last_start_time;
|
||||
uint16_t refresh_time;
|
||||
uint16_t w, h;
|
||||
uint16_t screen_w, screen_h;
|
||||
uint16_t video_w, video_h;
|
||||
uint16_t x0,y0,x1,y1;
|
||||
uint8_t line_buf_num;
|
||||
uint8_t rotate;
|
||||
uint8_t video_rotate;
|
||||
uint8_t hardware_auto_ks : 1, // 由应用层写入,由lcd模块读取
|
||||
get_auto_ks : 1, // 由应用层去读取,由lcd的模块去设置
|
||||
hardware_ready : 1,
|
||||
thread_exit : 1,
|
||||
rekick_lcd : 1;
|
||||
};
|
||||
extern struct app_lcd_s lcd_msg_s;
|
||||
|
||||
void lcd_arg_setting(uint16_t w, uint16_t h, uint8_t rotate, uint16_t screen_w, uint16_t screen_h,uint16_t video_w, uint16_t video_h, uint8_t video_rotate);
|
||||
void lcd_driver_init(const char *osd_encode_name, const char *lcd_osd_name, const char *lcd_video_p0, const char *lcd_video_p1);
|
||||
void wait_lcd_exit();
|
||||
void lcd_driver_reinit();
|
||||
void lcd_hardware_init(uint16_t *w, uint16_t *h, uint8_t *rotate, uint16_t *screen_w, uint16_t *screen_h,uint16_t *video_w, uint16_t *video_h, uint8_t *video_rotate);
|
||||
uint8_t g_read_hardware_auto_ks();
|
||||
uint8_t g_set_hardware_auto_ks(uint8_t en);
|
||||
|
||||
/*****************************osd_encode_msi******************************************/
|
||||
extern struct msi *osd_encode_msi_init(const char *name);
|
||||
/*************************************************************************************/
|
||||
|
||||
/*****************************lcd_osd_msi******************************************/
|
||||
struct msi *lcd_osd_msi(const char *name);
|
||||
struct lcd_osd_msi_s
|
||||
{
|
||||
struct lcdc_device *lcd_dev;
|
||||
struct msi *msi;
|
||||
struct framebuff *cur_show_data_s;
|
||||
struct framebuff *last_show_data_s;
|
||||
struct framebuff *delete_show_data_s;
|
||||
};
|
||||
/*************************************************************************************/
|
||||
|
||||
/*****************************lcd_video_msi******************************************/
|
||||
|
||||
struct msi *lcd_video_msi_init(const char *name, uint16_t filter);
|
||||
struct lcd_video_msi_s
|
||||
{
|
||||
struct msi *msi;
|
||||
uint16_t filter;
|
||||
struct framebuff *cur_fb;
|
||||
struct framebuff *last_fb;
|
||||
struct framebuff *delete_fb;
|
||||
};
|
||||
/*************************************************************************************/
|
||||
|
||||
/*****************************lvgl_osd_msi******************************************/
|
||||
|
||||
struct msi *lvgl_osd_msi(const char *name);
|
||||
struct framebuff *lvgl_osd_msi_get_fb(struct msi *msi);
|
||||
|
||||
typedef void (*osd_finish_cb)(void *self);
|
||||
typedef void (*osd_free_cb)(void *self, void *data);
|
||||
struct encode_data_s_callback
|
||||
{
|
||||
osd_finish_cb finish_cb;
|
||||
osd_free_cb free_cb;
|
||||
void * user_data;
|
||||
uint8_t rot_flag : 1,
|
||||
res : 7;
|
||||
};
|
||||
/*************************************************************************************/
|
||||
#endif
|
||||
632
sdk/app/app_lcd/lcd_msi.c
Normal file
632
sdk/app/app_lcd/lcd_msi.c
Normal file
@@ -0,0 +1,632 @@
|
||||
#include "basic_include.h"
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "app_lcd.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "user_work/user_work.h"
|
||||
|
||||
enum LCD_SHOW_MAP
|
||||
{
|
||||
LCD_OSD = BIT(0),
|
||||
LCD_P0 = BIT(1),
|
||||
LCD_P1 = BIT(2),
|
||||
LCD_P2 = BIT(3),
|
||||
};
|
||||
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define LCD_MSI_DEBUG(fmt, ...) // os_printf(fmt, ##__VA_ARGS__)
|
||||
|
||||
/* 中断 kick lcd 模式 */
|
||||
|
||||
typedef int32 (*lcdc_set_rotate_y_src_addr)(struct lcdc_device *p_lcdc, uint32 yaddr);
|
||||
typedef int32 (*lcdc_set_rotate_u_src_addr)(struct lcdc_device *p_lcdc, uint32 uaddr);
|
||||
typedef int32 (*lcdc_set_rotate_v_src_addr)(struct lcdc_device *p_lcdc, uint32 vaddr);
|
||||
|
||||
static void lcd_msi_irq_video_show(struct app_lcd_s *lcd_s, uint8_t which_video, uint8_t *p0_p1_enable, uint32_t *p_w, uint32_t *p_h)
|
||||
{
|
||||
struct msi *v_msi = NULL;
|
||||
struct lcd_video_msi_s *video = NULL;
|
||||
|
||||
struct framebuff *last_fb = NULL;
|
||||
uint8_t ret;
|
||||
uint32_t temp_w, temp_h;
|
||||
uint16_t *x = NULL;
|
||||
uint16_t *y = NULL;
|
||||
lcdc_set_rotate_y_src_addr p_lcdc_set_rotate_y_src_addr = NULL;
|
||||
lcdc_set_rotate_u_src_addr p_lcdc_set_rotate_u_src_addr = NULL;
|
||||
lcdc_set_rotate_v_src_addr p_lcdc_set_rotate_v_src_addr = NULL;
|
||||
|
||||
/*****************************************************************************************************
|
||||
* 要切换fb的条件分别是:
|
||||
* 1、检查delete的队列是否满了并且已经有显示过的fb,如果delete队列满了,那不能切换fb,需要保持原样,等待删除队列有空闲位置才能去切换
|
||||
* 2、需要检查当前是否有需要显示的,如果没有显示的,可以去从对应的队列获取fb去显示
|
||||
*****************************************************************************************************/
|
||||
if (which_video == 0)
|
||||
{
|
||||
video = (struct lcd_video_msi_s *) lcd_s->video_p0_msi->priv;
|
||||
|
||||
v_msi = lcd_s->video_p0_msi;
|
||||
last_fb = lcd_s->p0_fb;
|
||||
if (v_msi->enable)
|
||||
{
|
||||
x = &lcd_s->x0;
|
||||
y = &lcd_s->y0;
|
||||
p_lcdc_set_rotate_y_src_addr = lcdc_set_p0_rotate_y_src_addr;
|
||||
p_lcdc_set_rotate_u_src_addr = lcdc_set_p0_rotate_u_src_addr;
|
||||
p_lcdc_set_rotate_v_src_addr = lcdc_set_p0_rotate_v_src_addr;
|
||||
|
||||
// 如果上一次没有显示,则尝试从队列获取fb去显示
|
||||
if (!last_fb)
|
||||
{
|
||||
|
||||
RB_GET(&lcd_s->p0_rb, lcd_s->p0_fb);
|
||||
last_fb = lcd_s->p0_fb;
|
||||
}
|
||||
// 曾经显示过,就要检查一下delete rb是否还有空位,有空位才能切换fb
|
||||
else if (!RB_FULL(&lcd_s->delete_rb))
|
||||
{
|
||||
|
||||
// 检查是否有需要切换的fb
|
||||
ret = RB_GET(&lcd_s->p0_rb, lcd_s->p0_fb);
|
||||
// 更新切换的fb
|
||||
if (ret)
|
||||
{
|
||||
// 把需要删除的last fb放到delete rb的队列
|
||||
RB_SET(&lcd_s->delete_rb, last_fb);
|
||||
last_fb = lcd_s->p0_fb;
|
||||
}
|
||||
}
|
||||
// last fb存在和delete rb队列满了,则不需要切换,等待下次切换
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
// 使能被关闭,则需要清除显示的fb,那么要检查delete rb的队列是否为空
|
||||
else
|
||||
{
|
||||
|
||||
if (last_fb && !RB_FULL(&lcd_s->delete_rb))
|
||||
{
|
||||
|
||||
RB_SET(&lcd_s->delete_rb, last_fb);
|
||||
last_fb = NULL;
|
||||
lcd_s->p0_fb = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (which_video == 1)
|
||||
{
|
||||
v_msi = lcd_s->video_p1_msi;
|
||||
video = (struct lcd_video_msi_s *) lcd_s->video_p1_msi->priv;
|
||||
last_fb = lcd_s->p1_fb;
|
||||
if (v_msi->enable)
|
||||
{
|
||||
x = &lcd_s->x1;
|
||||
y = &lcd_s->y1;
|
||||
p_lcdc_set_rotate_y_src_addr = lcdc_set_p1_rotate_y_src_addr;
|
||||
p_lcdc_set_rotate_u_src_addr = lcdc_set_p1_rotate_u_src_addr;
|
||||
p_lcdc_set_rotate_v_src_addr = lcdc_set_p1_rotate_v_src_addr;
|
||||
|
||||
// 如果上一次没有显示,则尝试从队列获取fb去显示
|
||||
if (!last_fb)
|
||||
{
|
||||
RB_GET(&lcd_s->p1_rb, lcd_s->p1_fb);
|
||||
last_fb = lcd_s->p1_fb;
|
||||
}
|
||||
// 曾经显示过,就要检查一下delete rb是否还有空位,有空位才能切换fb
|
||||
else if (!RB_FULL(&lcd_s->delete_rb))
|
||||
{
|
||||
// 检查是否有需要切换的fb
|
||||
ret = RB_GET(&lcd_s->p1_rb, lcd_s->p1_fb);
|
||||
// 更新切换的fb
|
||||
if (ret)
|
||||
{
|
||||
// 把需要删除的last fb放到delete rb的队列
|
||||
RB_SET(&lcd_s->delete_rb, last_fb);
|
||||
last_fb = lcd_s->p1_fb;
|
||||
}
|
||||
}
|
||||
// last fb存在和delete rb队列满了,则不需要切换,等待下次切换
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
// 使能被关闭,则需要清除显示的fb,那么要检查delete rb的队列是否为空
|
||||
else
|
||||
{
|
||||
if (last_fb && !RB_FULL(&lcd_s->delete_rb))
|
||||
{
|
||||
RB_SET(&lcd_s->delete_rb, last_fb);
|
||||
last_fb = NULL;
|
||||
lcd_s->p1_fb = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (which_video == 2)
|
||||
{
|
||||
v_msi = lcd_s->csc_video_p2_msi;
|
||||
video = (struct lcd_video_msi_s *) lcd_s->csc_video_p2_msi->priv;
|
||||
last_fb = lcd_s->p2_fb;
|
||||
if (v_msi->enable)
|
||||
{
|
||||
x = &lcd_s->x0;
|
||||
y = &lcd_s->y0;
|
||||
p_lcdc_set_rotate_y_src_addr = lcdc_set_p0_rotate_y_src_addr;
|
||||
p_lcdc_set_rotate_u_src_addr = lcdc_set_p0_rotate_u_src_addr;
|
||||
p_lcdc_set_rotate_v_src_addr = lcdc_set_p0_rotate_v_src_addr;
|
||||
|
||||
// 如果上一次没有显示,则尝试从队列获取fb去显示
|
||||
if (!last_fb)
|
||||
{
|
||||
RB_GET(&lcd_s->p2_rb, lcd_s->p2_fb);
|
||||
last_fb = lcd_s->p2_fb;
|
||||
}
|
||||
// 曾经显示过,就要检查一下delete rb是否还有空位,有空位才能切换fb
|
||||
else if (!RB_FULL(&lcd_s->delete_rb))
|
||||
{
|
||||
// 检查是否有需要切换的fb
|
||||
ret = RB_GET(&lcd_s->p2_rb, lcd_s->p2_fb);
|
||||
// 更新切换的fb
|
||||
if (ret)
|
||||
{
|
||||
// 把需要删除的last fb放到delete rb的队列
|
||||
RB_SET(&lcd_s->delete_rb, last_fb);
|
||||
last_fb = lcd_s->p2_fb;
|
||||
}
|
||||
}
|
||||
// last fb存在和delete rb队列满了,则不需要切换,等待下次切换
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
// 使能被关闭,则需要清除显示的fb,那么要检查delete rb的队列是否为空
|
||||
else
|
||||
{
|
||||
if (last_fb && !RB_FULL(&lcd_s->delete_rb))
|
||||
{
|
||||
RB_SET(&lcd_s->delete_rb, last_fb);
|
||||
last_fb = NULL;
|
||||
lcd_s->p2_fb = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 需要将队列的数据清除
|
||||
if (!v_msi->enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
struct framebuff *fb = last_fb;
|
||||
|
||||
// 这里再次判断p_fb,保证非空才打开使能,有可能此时外部选择关闭
|
||||
if (fb)
|
||||
{
|
||||
*p0_p1_enable |= BIT(which_video);
|
||||
struct yuv_arg_s *yuv_msg = (struct yuv_arg_s *) fb->priv;
|
||||
uint32_t y_off = 0, uv_off = 0;
|
||||
uint8_t *p_buf = (uint8_t *) fb->data;
|
||||
|
||||
temp_w = yuv_msg->out_w;
|
||||
temp_h = yuv_msg->out_h;
|
||||
*p_w = temp_w;
|
||||
*p_h = temp_h;
|
||||
*x = yuv_msg->x;
|
||||
*y = yuv_msg->y;
|
||||
if (lcd_s->video_rotate == LCD_ROTATE_180)
|
||||
{
|
||||
y_off = temp_w * (temp_h - 1);
|
||||
uv_off = ((temp_w / 2 + 3) / 4) * 4 * (temp_h / 2 - 1);
|
||||
}
|
||||
LCD_MSI_DEBUG("p%d yuv_msg->y_size:%d \n", which_video, yuv_msg->y_size);
|
||||
p_lcdc_set_rotate_y_src_addr(lcd_s->lcd_dev, (uint32) p_buf + y_off);
|
||||
p_lcdc_set_rotate_u_src_addr(lcd_s->lcd_dev, (uint32) p_buf + yuv_msg->y_size + uv_off);
|
||||
p_lcdc_set_rotate_v_src_addr(lcd_s->lcd_dev, (uint32) p_buf + yuv_msg->y_size + yuv_msg->y_size / 4 + uv_off);
|
||||
}
|
||||
}
|
||||
|
||||
static void lcd_msi_irq_osd_show(struct app_lcd_s *lcd_s, uint8_t *osd_en)
|
||||
{
|
||||
|
||||
struct msi *v_msi = lcd_s->lcd_osd_msi;
|
||||
int32_t ret;
|
||||
struct framebuff *last_fb = lcd_s->osd_fb;
|
||||
|
||||
if (v_msi->enable)
|
||||
{
|
||||
|
||||
// 如果上一次没有显示,则尝试从队列获取fb去显示
|
||||
if (!last_fb)
|
||||
{
|
||||
|
||||
RB_GET(&lcd_s->osd_rb, lcd_s->osd_fb);
|
||||
last_fb = lcd_s->osd_fb;
|
||||
}
|
||||
// 曾经显示过,就要检查一下delete rb是否还有空位,有空位才能切换fb
|
||||
else if (!RB_FULL(&lcd_s->delete_rb))
|
||||
{
|
||||
|
||||
// 检查是否有需要切换的fb
|
||||
ret = RB_GET(&lcd_s->osd_rb, lcd_s->osd_fb);
|
||||
|
||||
// 更新切换的fb
|
||||
if (ret)
|
||||
{
|
||||
|
||||
// 把需要删除的last fb放到delete rb的队列
|
||||
RB_SET(&lcd_s->delete_rb, last_fb);
|
||||
|
||||
last_fb = lcd_s->osd_fb;
|
||||
}
|
||||
}
|
||||
// last fb存在和delete rb队列满了,则不需要切换,等待下次切换
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (last_fb && !RB_FULL(&lcd_s->delete_rb))
|
||||
{
|
||||
RB_SET(&lcd_s->delete_rb, last_fb);
|
||||
last_fb = NULL;
|
||||
lcd_s->osd_fb = NULL;
|
||||
}
|
||||
}
|
||||
// 这里再次判断osd_fb,保证非空才打开使能,有可能此时外部选择关闭
|
||||
|
||||
if (last_fb)
|
||||
{
|
||||
*osd_en = 1;
|
||||
lcdc_set_osd_dma_addr(lcd_s->lcd_dev, (uint32_t) last_fb->data);
|
||||
}
|
||||
}
|
||||
|
||||
int g_osd_en = 1;
|
||||
void lcd_msi_irq_callback(void *data)
|
||||
{
|
||||
struct app_lcd_s *lcd_s = (struct app_lcd_s *) data;
|
||||
uint8_t p0_p1_enable = 0;
|
||||
uint8_t osd_en = 0;
|
||||
uint32_t p0_w = 0, p0_h = 0, p1_w = 0, p1_h = 0;
|
||||
|
||||
// 设置 OSD 的 DMA 地址
|
||||
lcd_msi_irq_osd_show(lcd_s, &osd_en);
|
||||
|
||||
// 设置视频 P0 的地址
|
||||
lcd_msi_irq_video_show(lcd_s, 0, &p0_p1_enable, &p0_w, &p0_h);
|
||||
|
||||
// 设置视频 P1 的地址
|
||||
lcd_msi_irq_video_show(lcd_s, 1, &p0_p1_enable, &p1_w, &p1_h);
|
||||
|
||||
// 设置 CSC P2 的地址
|
||||
lcd_msi_irq_video_show(lcd_s, 2, &p0_p1_enable, &p0_w, &p0_h);
|
||||
|
||||
if (lcd_s->p2_fb && lcd_s->osd_fb)
|
||||
{
|
||||
uint32_t osd_fb_time = lcd_s->osd_fb->time;
|
||||
uint32_t p2_fb_time = lcd_s->p2_fb->time;
|
||||
|
||||
int32_t diff = osd_fb_time - p2_fb_time;
|
||||
struct framebuff *del_fb = NULL;
|
||||
uint8_t del_flag = 0;
|
||||
// 因为在中断,delete rb有空位,代表可以删除
|
||||
if (!RB_FULL(&lcd_s->delete_rb))
|
||||
{
|
||||
del_flag = 1;
|
||||
}
|
||||
// 需要移除一个fb,这里需要保证delete rb有空位,没有空位,则报一下错误(某些情况应该是异常显示,需要优化)
|
||||
if (diff > 0)
|
||||
{
|
||||
del_fb = lcd_s->p2_fb;
|
||||
p0_p1_enable &= ~BIT(2);
|
||||
if (del_flag)
|
||||
{
|
||||
lcd_s->p2_fb = NULL;
|
||||
}
|
||||
}
|
||||
else if (diff < 0)
|
||||
{
|
||||
del_fb = lcd_s->osd_fb;
|
||||
osd_en = 0;
|
||||
if (del_flag)
|
||||
{
|
||||
lcd_s->osd_fb = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
// 删除对应的fb
|
||||
if (del_flag)
|
||||
{
|
||||
RB_SET(&lcd_s->delete_rb, del_fb);
|
||||
}
|
||||
}
|
||||
|
||||
if (osd_en == 0 && p0_p1_enable == 0)
|
||||
{
|
||||
os_printf("(@@@@@@@@@@@)\n");
|
||||
}
|
||||
// 打开video
|
||||
if (p0_p1_enable)
|
||||
{
|
||||
// 检查一下line_buf是否已经申请了,申请空间就是w*line_num的空间(w应该是和屏旋转有关)
|
||||
uint16_t rotate_w;
|
||||
rotate_w = (lcd_s->video_w+15)/16*16;
|
||||
if (lcd_s->line_buf)
|
||||
{
|
||||
lcdc_set_rotate_linebuf_y_addr(lcd_s->lcd_dev, (uint32) lcd_s->line_buf);
|
||||
lcdc_set_rotate_linebuf_u_addr(lcd_s->lcd_dev, (uint32) lcd_s->line_buf + rotate_w * lcd_s->line_buf_num);
|
||||
lcdc_set_rotate_linebuf_v_addr(lcd_s->lcd_dev, (uint32) lcd_s->line_buf + rotate_w * lcd_s->line_buf_num + (rotate_w / 2) * lcd_s->line_buf_num);
|
||||
|
||||
LCD_MSI_DEBUG("p0_w:%d p0_h:%d p1_w:%d p1_h:%d\n", p0_w, p0_h, p1_w, p1_h);
|
||||
lcdc_set_rotate_p0p1_size(lcd_s->lcd_dev, p0_w, p0_h, p1_w, p1_h);
|
||||
lcdc_set_rotate_mirror(lcd_s->lcd_dev, 0, lcd_s->video_rotate);
|
||||
|
||||
if (lcd_s->video_rotate == LCD_ROTATE_180)
|
||||
{
|
||||
lcdc_set_video_start_location(lcd_s->lcd_dev, 0, 0);
|
||||
lcdc_set_rotate_p0p1_start_location(lcd_s->lcd_dev, lcd_s->x0, 0, lcd_s->x1, lcd_s->y1);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcdc_set_video_start_location(lcd_s->lcd_dev, 0, 0);
|
||||
lcdc_set_rotate_p0p1_start_location(lcd_s->lcd_dev, lcd_s->x0, lcd_s->y0, lcd_s->x1, lcd_s->y1);
|
||||
}
|
||||
|
||||
lcdc_set_p0p1_enable(lcd_s->lcd_dev, (p0_p1_enable & BIT(0)) ? 1 : (p0_p1_enable & BIT(2)), p0_p1_enable & BIT(1));
|
||||
|
||||
lcdc_set_video_en(lcd_s->lcd_dev, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcdc_set_video_en(lcd_s->lcd_dev, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lcd_s->free_line_buf && lcd_s->line_buf)
|
||||
{
|
||||
LCD_MSI_DEBUG("-----------force free video line buff:0x%x-----------\n", lcd_s->free_line_buf);
|
||||
STREAM_LIBC_FREE(lcd_s->free_line_buf);
|
||||
lcd_s->free_line_buf = NULL;
|
||||
}
|
||||
if (lcd_s->line_buf)
|
||||
{
|
||||
lcd_s->free_line_buf = lcd_s->line_buf;
|
||||
lcd_s->line_buf = NULL;
|
||||
}
|
||||
lcdc_set_video_en(lcd_s->lcd_dev, 0);
|
||||
}
|
||||
|
||||
lcdc_set_osd_en(lcd_s->lcd_dev, osd_en);
|
||||
|
||||
lcdc_set_timeout_info(lcd_s->lcd_dev, 1, 3);
|
||||
|
||||
lcdc_set_start_run(lcd_s->lcd_dev);
|
||||
|
||||
lcd_s->start_time = os_jiffies();
|
||||
}
|
||||
|
||||
// 检查如果被关闭了,则清空队列,这里有个问题,如果使能被关闭后立刻打开,是不会清空队列的,这个要考虑后续如何去处理
|
||||
void clear_msi_fb(struct msi *v_msi)
|
||||
{
|
||||
struct framebuff *fb;
|
||||
while (v_msi)
|
||||
{
|
||||
fb = msi_get_fb(v_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
os_printf("msi name:%s\tfb:%X\n", v_msi->name, fb);
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int32 lcd_msi_work(struct os_work *work)
|
||||
{
|
||||
struct app_lcd_s *lcd_s = (struct app_lcd_s *) work;
|
||||
|
||||
struct lcd_video_msi_s *video_p0 = NULL;
|
||||
struct lcd_video_msi_s *video_p1 = NULL;
|
||||
struct lcd_video_msi_s *csc_video_p2 = NULL;
|
||||
struct lcd_osd_msi_s *osd_show = NULL;
|
||||
|
||||
struct framebuff *fb;
|
||||
uint32_t lcd_show_map = 0;
|
||||
uint32_t temp = 0;
|
||||
|
||||
static int count = 0;
|
||||
|
||||
osd_show = (struct lcd_osd_msi_s *) lcd_s->lcd_osd_msi->priv;
|
||||
video_p0 = (struct lcd_video_msi_s *) lcd_s->video_p0_msi->priv;
|
||||
video_p1 = (struct lcd_video_msi_s *) lcd_s->video_p1_msi->priv;
|
||||
csc_video_p2 = (struct lcd_video_msi_s *) lcd_s->csc_video_p2_msi->priv;
|
||||
|
||||
// 如果不需要显示video,则空间释放吧
|
||||
if (lcd_s->free_line_buf)
|
||||
{
|
||||
LCD_MSI_DEBUG("-----------free video line buff:0x%x-----------\n", lcd_s->free_line_buf);
|
||||
|
||||
irq_disable(LCD_IRQn);
|
||||
temp = (uint32_t) lcd_s->free_line_buf;
|
||||
lcd_s->free_line_buf = NULL;
|
||||
irq_enable(LCD_IRQn);
|
||||
|
||||
STREAM_LIBC_FREE((void *) temp);
|
||||
}
|
||||
|
||||
// 检查一下是否有fb需要删除,从delete rb里面查找
|
||||
while (!RB_EMPTY(&lcd_s->delete_rb))
|
||||
{
|
||||
RB_GET(&lcd_s->delete_rb, fb);
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
|
||||
// 检查是否需要清空队列,一个一个清空(通过使能位来判断,如果使能被关闭,则清空对应的队列)
|
||||
// 这里没有考虑正在显示的情况,正在显示的由中断去放到delete rb的队列
|
||||
// 将对应rb队列清空(由于ringbuf结构体原因,暂时没有通用函数,先在这里清空)
|
||||
if (!lcd_s->lcd_osd_msi->enable)
|
||||
{
|
||||
clear_msi_fb(lcd_s->lcd_osd_msi);
|
||||
while (!RB_EMPTY(&lcd_s->osd_rb))
|
||||
{
|
||||
// 因为get会在中断使用,所以这里采用安全方式去读取,防止异步问题
|
||||
if (RB_INT_GET(&lcd_s->osd_rb, fb))
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!lcd_s->video_p0_msi->enable)
|
||||
{
|
||||
clear_msi_fb(lcd_s->video_p0_msi);
|
||||
while (!RB_EMPTY(&lcd_s->p0_rb))
|
||||
{
|
||||
// 因为get会在中断使用,所以这里采用安全方式去读取,防止异步问题
|
||||
if (RB_INT_GET(&lcd_s->p0_rb, fb))
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!lcd_s->video_p1_msi->enable)
|
||||
{
|
||||
clear_msi_fb(lcd_s->video_p1_msi);
|
||||
while (!RB_EMPTY(&lcd_s->p1_rb))
|
||||
{
|
||||
// 因为get会在中断使用,所以这里采用安全方式去读取,防止异步问题
|
||||
if (RB_INT_GET(&lcd_s->p1_rb, fb))
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!lcd_s->csc_video_p2_msi->enable)
|
||||
{
|
||||
clear_msi_fb(lcd_s->csc_video_p2_msi);
|
||||
while (!RB_EMPTY(&lcd_s->p2_rb))
|
||||
{
|
||||
// 因为get会在中断使用,所以这里采用安全方式去读取,防止异步问题
|
||||
if (RB_INT_GET(&lcd_s->p2_rb, fb))
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将获取到对应的fb放到队列里面,如果被disable,需要将队列清空
|
||||
if (!RB_FULL(&lcd_s->osd_rb))
|
||||
{
|
||||
fb = msi_get_fb(lcd_s->lcd_osd_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
RB_SET(&lcd_s->osd_rb, fb);
|
||||
}
|
||||
}
|
||||
|
||||
if (!RB_FULL(&lcd_s->p0_rb))
|
||||
{
|
||||
fb = msi_get_fb(lcd_s->video_p0_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
RB_SET(&lcd_s->p0_rb, fb);
|
||||
}
|
||||
}
|
||||
|
||||
if (!RB_FULL(&lcd_s->p1_rb))
|
||||
{
|
||||
fb = msi_get_fb(lcd_s->video_p1_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
RB_SET(&lcd_s->p1_rb, fb);
|
||||
}
|
||||
}
|
||||
|
||||
if (!RB_FULL(&lcd_s->p2_rb))
|
||||
{
|
||||
fb = msi_get_fb(lcd_s->csc_video_p2_msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
RB_SET(&lcd_s->p2_rb, fb);
|
||||
}
|
||||
}
|
||||
|
||||
// 检查队列是否为空
|
||||
if (lcd_s->osd_fb || !RB_EMPTY(&lcd_s->osd_rb))
|
||||
{
|
||||
lcd_show_map |= LCD_OSD;
|
||||
}
|
||||
|
||||
if (lcd_s->p0_fb || !RB_EMPTY(&lcd_s->p0_rb))
|
||||
{
|
||||
lcd_show_map |= LCD_P0;
|
||||
}
|
||||
|
||||
if (lcd_s->p1_fb || !RB_EMPTY(&lcd_s->p1_rb))
|
||||
{
|
||||
lcd_show_map |= LCD_P1;
|
||||
}
|
||||
|
||||
if (lcd_s->p2_fb || !RB_EMPTY(&lcd_s->p2_rb))
|
||||
{
|
||||
lcd_show_map |= LCD_P2;
|
||||
}
|
||||
|
||||
// 如果p0和p1、p2的队列不为空,则要尝试申请空间
|
||||
if (lcd_show_map & (LCD_P0 | LCD_P1 | LCD_P2))
|
||||
{
|
||||
uint16_t rotate_w;
|
||||
rotate_w = (lcd_s->video_w+15)/16*16;
|
||||
// 这里理论要申请到空间,如果申请失败,重新申请一下(否则要就额外处理资源数据)
|
||||
if (!lcd_s->line_buf)
|
||||
{
|
||||
lcd_s->line_buf = (void *) STREAM_LIBC_MALLOC(lcd_s->line_buf_num * rotate_w * 2);
|
||||
LCD_MSI_DEBUG("-----------alloc video line buff:0x%x-----------\n", lcd_s->line_buf);
|
||||
}
|
||||
// 空间申请失败,是尝试等待申请空间还是清空队列?这里就是等待下次申请空间去尝试吧
|
||||
if (!lcd_s->line_buf)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (lcd_show_map)
|
||||
{
|
||||
lcd_s->hardware_ready = 0; // 标记fb已准备好,等待刷新
|
||||
}
|
||||
else
|
||||
{
|
||||
goto __lcd_msi_work_end;
|
||||
}
|
||||
|
||||
if ((!count && !lcd_s->hardware_ready) || lcd_s->rekick_lcd)
|
||||
{
|
||||
count++;
|
||||
lcd_s->rekick_lcd = 0;
|
||||
LCD_MSI_DEBUG("=========first kick lcd=========\n");
|
||||
lcd_s->app_lcd_cb(lcd_s);
|
||||
}
|
||||
|
||||
__lcd_msi_work_end:
|
||||
os_run_work_delay(&lcd_s->work, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
86
sdk/app/app_lcd/lcd_osd_msi.c
Normal file
86
sdk/app/app_lcd/lcd_osd_msi.c
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "app_lcd.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
// 这里只是为了给osd创建流,实际内部没有做什么,这个流取到的数据应该是已经压缩过的
|
||||
// 接收到就可以配置硬件寄存器了
|
||||
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define MAX_OSD_SHOW_RX 8
|
||||
|
||||
static int lcd_osd_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct lcd_osd_msi_s *show = (struct lcd_osd_msi_s *)msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
|
||||
// 暂时没有考虑释放
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
|
||||
STREAM_LIBC_FREE(show);
|
||||
}
|
||||
break;
|
||||
// 接收,判断是否已经压缩了
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
if(fb->mtype != F_ERGB)
|
||||
{
|
||||
ret = RET_ERR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_LCD_OSD:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_OSD_ENABLE:
|
||||
{
|
||||
msi->enable = arg;
|
||||
os_printf("---MSI_OSD_ENABLE :%d----\n",msi->enable);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
struct msi *lcd_osd_msi(const char *name)
|
||||
{
|
||||
struct msi *msi = msi_new(name, MAX_OSD_SHOW_RX, NULL);
|
||||
struct lcd_osd_msi_s *show = (struct lcd_osd_msi_s *)msi->priv;
|
||||
struct lcdc_device *lcd_dev;
|
||||
if (!show)
|
||||
{
|
||||
show = (struct lcd_osd_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct lcd_osd_msi_s));
|
||||
lcd_dev = (struct lcdc_device *)dev_get(HG_LCDC_DEVID);
|
||||
show->lcd_dev = lcd_dev;
|
||||
msi->action = lcd_osd_msi_action;
|
||||
show->msi = msi;
|
||||
msi->priv = (void *)show;
|
||||
msi->enable = 1;
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
88
sdk/app/app_lcd/lcd_video_msi.c
Normal file
88
sdk/app/app_lcd/lcd_video_msi.c
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "app_lcd.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define MAX_LCD_VIDEO 8
|
||||
|
||||
static int lcd_video_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct lcd_video_msi_s *lcd_video = (struct lcd_video_msi_s *)msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
|
||||
// 暂时没有考虑释放
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
STREAM_LIBC_FREE(lcd_video);
|
||||
}
|
||||
break;
|
||||
// 类型不匹配,就不需要接收
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
if((fb->mtype != F_YUV) || (fb->stype != lcd_video->filter))
|
||||
{
|
||||
ret = RET_ERR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_LCD_VIDEO:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_VIDEO_ENABLE:
|
||||
{
|
||||
msi->enable = arg;
|
||||
os_printf("---%s MSI_VIDEO_ENABLE :%d----\n",msi->name, msi->enable);
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_VIDEO_GET_ENABLE:
|
||||
{
|
||||
uint32_t *val = (uint32_t *)param2;
|
||||
// os_printf("---%s get enable:%d-----\n",msi->name, msi->enable);
|
||||
*val = msi->enable;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *lcd_video_msi_init(const char *name, uint16_t filter)
|
||||
{
|
||||
struct msi *msi = msi_new(name, MAX_LCD_VIDEO, NULL);
|
||||
struct lcd_video_msi_s *lcd_video = (struct lcd_video_msi_s *)msi->priv;
|
||||
if (!lcd_video)
|
||||
{
|
||||
lcd_video = (struct lcd_video_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct lcd_video_msi_s));
|
||||
lcd_video->msi = msi;
|
||||
lcd_video->filter = filter;
|
||||
msi->priv = (void *)lcd_video;
|
||||
msi->enable = 1;
|
||||
msi->action = lcd_video_msi_action;
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
132
sdk/app/app_lcd/lvgl_osd_msi.c
Normal file
132
sdk/app/app_lcd/lvgl_osd_msi.c
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "app_lcd.h"
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define MAX_LVGL_OSD_TX 2
|
||||
|
||||
struct lvgl_osd_msi_s
|
||||
{
|
||||
struct msi *msi;
|
||||
struct fbpool tx_pool;
|
||||
};
|
||||
|
||||
static int lvgl_osd_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct lvgl_osd_msi_s *lvgl_osd = (struct lvgl_osd_msi_s *)msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
// 暂时没有考虑释放
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
struct framebuff *fb;
|
||||
// 释放资源fb资源文件,priv是独立申请的
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&lvgl_osd->tx_pool, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&lvgl_osd->tx_pool);
|
||||
STREAM_LIBC_FREE(lvgl_osd);
|
||||
}
|
||||
break;
|
||||
// 接收,判断是类型是否可以支持压缩
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
|
||||
struct encode_data_s_callback *callback = (struct encode_data_s_callback *)fb->priv;
|
||||
if (callback->finish_cb)
|
||||
{
|
||||
callback->finish_cb(callback->user_data);
|
||||
}
|
||||
if (callback->free_cb)
|
||||
{
|
||||
callback->free_cb(callback->user_data, fb->data);
|
||||
}
|
||||
// 这个data可能是lvgl那边的,暂时不需要释放
|
||||
fb->data = NULL;
|
||||
callback->finish_cb = NULL;
|
||||
callback->free_cb = NULL;
|
||||
callback->user_data = NULL;
|
||||
// msi_get_fb(NULL,fb);
|
||||
|
||||
fbpool_put(&lvgl_osd->tx_pool, fb);
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct framebuff *lvgl_osd_msi_get_fb(struct msi *msi)
|
||||
{
|
||||
struct lvgl_osd_msi_s *lvgl_osd = (struct lvgl_osd_msi_s *)msi->priv;
|
||||
struct framebuff *fb = fbpool_get(&lvgl_osd->tx_pool, 0, lvgl_osd->msi);
|
||||
if(fb)
|
||||
{
|
||||
fb->mtype = F_RGB;
|
||||
fb->stype = LVGL_RGB;
|
||||
}
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
// 拷贝osd到内存,然后发送出去,使用workqueue去作为任务吧
|
||||
struct msi *lvgl_osd_msi(const char *name)
|
||||
{
|
||||
struct msi *msi = msi_new(name, 0, NULL);
|
||||
|
||||
struct lvgl_osd_msi_s *lvgl_osd = (struct lvgl_osd_msi_s *)msi->priv;
|
||||
|
||||
if (!lvgl_osd)
|
||||
{
|
||||
lvgl_osd = (struct lvgl_osd_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct lvgl_osd_msi_s));
|
||||
|
||||
lvgl_osd->msi = msi;
|
||||
|
||||
fbpool_init(&lvgl_osd->tx_pool, MAX_LVGL_OSD_TX);
|
||||
int init_count = 0;
|
||||
void *priv;
|
||||
// 初始化framebuffer节点数量空间?最后由workqueue去从ringbuf去获取一个节点
|
||||
while (init_count < MAX_LVGL_OSD_TX)
|
||||
{
|
||||
priv = (void *)STREAM_LIBC_ZALLOC(sizeof(struct encode_data_s_callback));
|
||||
FBPOOL_SET_INFO(&lvgl_osd->tx_pool, init_count, NULL, 0, priv);
|
||||
init_count++;
|
||||
}
|
||||
msi->priv = (void *)lvgl_osd;
|
||||
msi->action = lvgl_osd_msi_action;
|
||||
msi->enable = 1;
|
||||
msi_add_output(lvgl_osd->msi, NULL, R_OSD_ENCODE);
|
||||
msi_add_output(lvgl_osd->msi, NULL, R_CSC_MSI);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
314
sdk/app/app_lcd/osd_encode_msi.c
Normal file
314
sdk/app/app_lcd/osd_encode_msi.c
Normal file
@@ -0,0 +1,314 @@
|
||||
#include "stream_frame.h"
|
||||
#include "osal/work.h"
|
||||
#include "basic_include.h"
|
||||
|
||||
#include "lib/multimedia/msi.h"
|
||||
|
||||
#include "hal/osd_enc.h"
|
||||
#include "dev/osd_enc/hgosd_enc.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define MAX_OSD_ENCODE_RX 8
|
||||
#define MAX_OSD_ENCODE_TX 8
|
||||
|
||||
struct osd_encode_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct osdenc_device *osd_enc_dev;
|
||||
struct msi *msi;
|
||||
uint8_t *osd_tmp_buf;
|
||||
uint32_t osd_tmp_buf_size;
|
||||
|
||||
struct fbpool tx_pool;
|
||||
|
||||
struct framebuff *parent_data_s;
|
||||
|
||||
// osd压缩后的数据长度
|
||||
uint32_t data_len;
|
||||
uint32_t start_time;
|
||||
// 解码模块是否可用
|
||||
uint8_t hardware_ready;
|
||||
};
|
||||
|
||||
static int32 osd_enc_isr_msi(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
struct osd_encode_msi_s *osd_enc = (struct osd_encode_msi_s *)irq_data;
|
||||
struct osdenc_device *osd_enc_dev;
|
||||
struct msi *osd_enc_msi = (struct msi *)osd_enc->msi;
|
||||
osd_enc_dev = osd_enc->osd_enc_dev;
|
||||
// _os_printf("=");
|
||||
msi_do_cmd(osd_enc_msi, MSI_CMD_OSD_ENCODE, MSI_OSD_HARDWARE_ENCODE_SET_LEN, osd_enc_dlen(osd_enc_dev));
|
||||
msi_do_cmd(osd_enc_msi, MSI_CMD_OSD_ENCODE, MSI_OSD_HARDWARE_REAY_CMD, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32 osd_encode_work(struct os_work *work)
|
||||
{
|
||||
struct osd_encode_msi_s *osd_encode = (struct osd_encode_msi_s *)work;
|
||||
struct framebuff *data_s = NULL;
|
||||
// static int osd_encode_count = 0;
|
||||
static uint32_t osd_send_times = 0;
|
||||
// 先检测一下解码模块是否可用
|
||||
if (osd_encode->hardware_ready)
|
||||
{
|
||||
// 检测一下是否有data_s需要先发送出去
|
||||
if (osd_encode->parent_data_s)
|
||||
{
|
||||
// 获取data_s,申请空间,发送数据
|
||||
data_s = fbpool_get(&osd_encode->tx_pool, 0, osd_encode->msi);
|
||||
if (data_s)
|
||||
{
|
||||
data_s->mtype = F_ERGB; //设置为已经压缩的RGB
|
||||
data_s->stype = osd_encode->parent_data_s->stype; //子类保持与接收一致
|
||||
msi_delete_fb(NULL, osd_encode->parent_data_s);
|
||||
osd_encode->parent_data_s = NULL;
|
||||
|
||||
// 为data_s申请空间
|
||||
data_s->data = (void *)STREAM_MALLOC(osd_encode->data_len);
|
||||
if (data_s->data)
|
||||
{
|
||||
// 先清除cache
|
||||
sys_dcache_invalid_range((uint32_t *)data_s->data, osd_encode->data_len);
|
||||
// 拷贝数据
|
||||
hw_memcpy_no_cache(data_s->data, (const void *)msi_do_cmd(osd_encode->msi, MSI_CMD_OSD_ENCODE, MSI_OSD_HARDWARE_ENCODE_BUF, 0), (uint32_t)osd_encode->data_len);
|
||||
//sys_dcache_clean_range((uint32_t *)data_s->data, osd_encode->data_len);
|
||||
// 数据类型保持一致
|
||||
data_s->len = osd_encode->data_len;
|
||||
data_s->time = os_jiffies();
|
||||
// os_printf("osd encode after len:%d\n",data_s->len);
|
||||
// os_printf("encode spend time:%d\n",(uint32_t)os_jiffies()-osd_encode->start_time);
|
||||
msi_output_fb(osd_encode->msi, data_s);
|
||||
//os_printf("success:%d\n",success);
|
||||
osd_send_times++;
|
||||
}
|
||||
// 没有发送成功,则释放data_s先吧,下一次再发送
|
||||
else
|
||||
{
|
||||
|
||||
msi_delete_fb(osd_encode->msi, data_s);
|
||||
_os_printf("**********************");
|
||||
}
|
||||
|
||||
data_s = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// 重新检测一下,parent_data_s是否还存在,不存在就去看看是否有需要压缩的osd
|
||||
// 会进入中断
|
||||
if (!osd_encode->parent_data_s)
|
||||
{
|
||||
osd_encode->parent_data_s = msi_get_fb(osd_encode->msi, 0);
|
||||
if (osd_encode->parent_data_s)
|
||||
{
|
||||
// 判断一下osd_tmp_buf_size是否足够,如果足够就不需要重新申请空间,否则重新申请一下空间
|
||||
if (osd_encode->osd_tmp_buf_size < osd_encode->parent_data_s->len)
|
||||
{
|
||||
// 释放原来空间
|
||||
if (osd_encode->osd_tmp_buf)
|
||||
{
|
||||
STREAM_FREE(osd_encode->osd_tmp_buf);
|
||||
}
|
||||
|
||||
// 重新申请一下空间
|
||||
osd_encode->osd_tmp_buf = (uint8_t *)STREAM_MALLOC(osd_encode->parent_data_s->len);
|
||||
// 申请失败,不压缩了,丢弃
|
||||
if (!osd_encode->osd_tmp_buf)
|
||||
{
|
||||
osd_encode->osd_tmp_buf_size = 0;
|
||||
msi_delete_fb(NULL, osd_encode->parent_data_s);
|
||||
osd_encode->parent_data_s = NULL;
|
||||
goto osd_encode_work_end;
|
||||
}
|
||||
osd_encode->osd_tmp_buf_size = osd_encode->parent_data_s->len;
|
||||
// 先清除cache
|
||||
sys_dcache_invalid_range((uint32_t *)osd_encode->osd_tmp_buf, osd_encode->osd_tmp_buf_size);
|
||||
}
|
||||
|
||||
// 硬件模块开始被使用,标志置一下
|
||||
msi_do_cmd(osd_encode->msi, MSI_CMD_OSD_ENCODE, MSI_OSD_HARDWARE_REAY_CMD, 0);
|
||||
// 去压缩
|
||||
osd_enc_addr(osd_encode->osd_enc_dev, (uint32)osd_encode->parent_data_s->data, (uint32)msi_do_cmd(osd_encode->msi, MSI_CMD_OSD_ENCODE, MSI_OSD_HARDWARE_ENCODE_BUF, 0));
|
||||
osd_enc_src_len(osd_encode->osd_enc_dev, osd_encode->osd_tmp_buf_size);
|
||||
osd_encode->start_time = os_jiffies();
|
||||
osd_enc_run(osd_encode->osd_enc_dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
osd_encode_work_end:
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32 osd_encode_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct osd_encode_msi_s *osd_encode = (struct osd_encode_msi_s *)msi->priv;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_id)
|
||||
{
|
||||
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&osd_encode->work, 1);
|
||||
// lcdc_osd_enc_start_run(osd_encode->osd_enc_dev, 0);
|
||||
|
||||
// 释放资源空间
|
||||
if (osd_encode->osd_tmp_buf)
|
||||
{
|
||||
STREAM_FREE(osd_encode->osd_tmp_buf);
|
||||
osd_encode->osd_tmp_buf_size = 0;
|
||||
osd_encode->osd_tmp_buf = NULL;
|
||||
}
|
||||
|
||||
// 将缓冲区的fb释放
|
||||
struct framebuff *fb;
|
||||
while (1)
|
||||
{
|
||||
fb = msi_get_fb(osd_encode->msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (osd_encode->parent_data_s)
|
||||
{
|
||||
msi_delete_fb(NULL, osd_encode->parent_data_s);
|
||||
osd_encode->parent_data_s = NULL;
|
||||
}
|
||||
|
||||
// 由于tx_pool的fb没有特殊空间,直接释放就好了
|
||||
fbpool_destroy(&osd_encode->tx_pool);
|
||||
break;
|
||||
}
|
||||
// 暂时没有考虑释放
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
STREAM_LIBC_FREE(osd_encode);
|
||||
}
|
||||
break;
|
||||
// 接收,判断是类型是否可以支持压缩,暂时默认全部接收
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
if(fb->mtype != F_RGB || fb->srcID != FRAMEBUFF_SOURCE_OSD_ENC)
|
||||
{
|
||||
ret = RET_ERR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
fbpool_put(&osd_encode->tx_pool, fb);
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_OSD_ENCODE:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_OSD_HARDWARE_REAY_CMD:
|
||||
osd_encode->hardware_ready = arg;
|
||||
break;
|
||||
|
||||
case MSI_OSD_HARDWARE_ENCODE_SET_LEN:
|
||||
osd_encode->data_len = arg;
|
||||
break;
|
||||
|
||||
case MSI_OSD_HARDWARE_ENCODE_GET_LEN:
|
||||
ret = osd_encode->data_len;
|
||||
break;
|
||||
|
||||
case MSI_OSD_HARDWARE_ENCODE_BUF:
|
||||
ret = (uint32_t)osd_encode->osd_tmp_buf;
|
||||
break;
|
||||
|
||||
case MSI_OSD_HARDWARE_DEV:
|
||||
ret = (uint32_t)osd_encode->osd_enc_dev;
|
||||
break;
|
||||
|
||||
case MSI_OSD_HARDWARE_STREAM_RESET:
|
||||
{
|
||||
// 硬件模块可用
|
||||
osd_encode->hardware_ready = 1;
|
||||
OS_WORK_REINIT(&osd_encode->work);
|
||||
os_run_work(&osd_encode->work);
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_OSD_HARDWARE_STREAM_STOP:
|
||||
// 停止硬件模块
|
||||
// lcdc_osd_enc_start_run(osd_encode->osd_enc_dev, 0);
|
||||
// workqueue停止
|
||||
os_work_cancle2(&osd_encode->work, 1);
|
||||
break;
|
||||
|
||||
case MSI_OSD_ENC_MSI_ENABLE:
|
||||
osd_encode->msi->enable = arg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// osd压缩是一个模块,所以在这里统一管理自己的模块,所有需要压缩的数据都到这里,然后再发出去
|
||||
// 然后类型可以跟着父流一致
|
||||
// 要预先申请一个空间给到osd压缩,最后再读取寄存器看看要拷贝多少压缩的数据
|
||||
// 所以空间是:w*h*2+压缩的size,压缩的size根据不同ui去压缩的,一般不会超过原来的size
|
||||
|
||||
struct msi *osd_encode_msi_init(const char *name)
|
||||
{
|
||||
struct msi *msi = msi_new(name, MAX_OSD_ENCODE_RX, NULL); //R_OSD_ENCODE
|
||||
struct osd_encode_msi_s *osd_encode = (struct osd_encode_msi_s *)msi->priv;
|
||||
if (!osd_encode)
|
||||
{
|
||||
osd_encode = (struct osd_encode_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct osd_encode_msi_s));
|
||||
msi->priv = (void *)osd_encode;
|
||||
osd_encode->msi = msi;
|
||||
fbpool_init(&osd_encode->tx_pool, MAX_OSD_ENCODE_TX);
|
||||
osd_encode->osd_enc_dev = (struct osdenc_device *)dev_get(HG_OSD_ENC_DEVID);
|
||||
osd_encode->hardware_ready = 1;
|
||||
osd_encode->osd_tmp_buf_size = 0;
|
||||
osd_encode->osd_tmp_buf = NULL;
|
||||
msi->action = osd_encode_msi_action;
|
||||
msi->enable = 1;
|
||||
msi_add_output(osd_encode->msi, NULL, R_LCD_OSD);
|
||||
|
||||
osd_enc_open(osd_encode->osd_enc_dev);
|
||||
osd_enc_tran_config(osd_encode->osd_enc_dev, 0xFFFFFF, 0xFFFFFF, 0x000000, 0x000000);
|
||||
osd_enc_set_format(osd_encode->osd_enc_dev, 1);
|
||||
osd_enc_request_irq(osd_encode->osd_enc_dev, ENC_DONE_IRQ, osd_enc_isr_msi, (uint32)osd_encode);
|
||||
OS_WORK_INIT(&osd_encode->work, osd_encode_work, 0);
|
||||
os_run_work_delay(&osd_encode->work, 1);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
553
sdk/app/app_lcd/sim_video_more_msi.c
Normal file
553
sdk/app/app_lcd/sim_video_more_msi.c
Normal file
@@ -0,0 +1,553 @@
|
||||
/**********************************************************************************************************
|
||||
* 虚拟屏幕,支持更多的屏,顶层序号大,底层序号低
|
||||
* ********************************************************************************************************/
|
||||
#include "basic_include.h"
|
||||
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "osal/work.h"
|
||||
#include "stream_define.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "app_lcd/app_lcd.h"
|
||||
#include "user_work/user_work.h"
|
||||
|
||||
extern void yuv_blk_cpy(uint8 *des, uint8* src,uint32 des_w,uint32 des_h, uint32 src_w, uint32_t src_h,uint32 x,uint32 y);
|
||||
extern void yuv_blk_reduce(uint8 *des, uint8* src,uint32 des_w,uint32 des_h, uint32 src_w, uint32_t src_h,uint32 x,uint32 y);
|
||||
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define MAX_RX 8
|
||||
#define MAX_TX 2
|
||||
|
||||
struct window_msg{
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
};
|
||||
|
||||
struct sim_video_more_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct fbpool tx_pool;
|
||||
uint16_t w, h;
|
||||
uint16_t *filter; // 数组去进行过滤,0为结束
|
||||
struct framebuff **screen; // 不同屏幕的framebuff,屏幕数量与filter数量一致
|
||||
uint16_t screen_num;
|
||||
uint32_t bufadr[MAX_TX];
|
||||
struct framebuff *last_fb;
|
||||
struct framebuff *last_input_fb;
|
||||
uint32_t subwindow_cnt[10]; //本地buf所记录的cnt
|
||||
uint32_t dispwindow_cnt[10]; //显示的buf所记录的cnt
|
||||
struct window_msg dsp_window_msg[10];
|
||||
uint8_t video_display_mask[10]; //记录哪个界面打开了独显,正常只可能有一个设备配置上,或者没人配置上
|
||||
uint8_t lcd_fb_updata;
|
||||
};
|
||||
|
||||
//只做双层
|
||||
static int32 sim_video_more_work(struct os_work *work)
|
||||
{
|
||||
struct sim_video_more_msi_s *sim_video = (struct sim_video_more_msi_s *)work;
|
||||
struct framebuff *fb;
|
||||
struct framebuff *output_fb;
|
||||
uint32_t dispbuf;
|
||||
fb = msi_get_fb(sim_video->msi, 0);
|
||||
// 接收到一个fb,就需要判断类型(p0,p1),然后申请空间去进行叠层
|
||||
if (fb)
|
||||
{
|
||||
// 查看类型是否匹配(正常到这里一定匹配,因为接收的时候就进行过滤了)
|
||||
uint16_t match_count = 0;
|
||||
uint8_t match_flag = 0;
|
||||
|
||||
while (match_count < sim_video->screen_num)
|
||||
{
|
||||
if (fb->stype == sim_video->filter[match_count]) //类型检查,看一下当前的fb类型是否存在于过滤网内
|
||||
{
|
||||
if (sim_video->screen[match_count]) //检查当前的screen是否存在,如果存在,则删除,更新新的fb到screen
|
||||
{
|
||||
msi_delete_fb(NULL, sim_video->screen[match_count]);
|
||||
}
|
||||
sim_video->screen[match_count] = fb;
|
||||
match_flag = 1;
|
||||
break;
|
||||
}
|
||||
match_count++;
|
||||
}
|
||||
|
||||
// 没有匹配,删除,并且不需要刷新
|
||||
if (!match_flag)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
goto sim_video_work_end;
|
||||
}
|
||||
|
||||
output_fb = fbpool_get(&sim_video->tx_pool, 0, sim_video->msi); //从sim_video的发送池里找到对应的fb
|
||||
if (!output_fb)
|
||||
{
|
||||
goto sim_video_work_end;
|
||||
}
|
||||
|
||||
if((uint32_t)output_fb->data == sim_video->bufadr[0]){
|
||||
dispbuf = sim_video->bufadr[1]; //提取当前正在显示的buf地址,用来拷数据
|
||||
}else{
|
||||
dispbuf = sim_video->bufadr[0];
|
||||
}
|
||||
|
||||
// 这个模式是默认都是叠层,不再判断有某些情况不需要叠层的情况(效率低,但是既然应用设定多个屏幕,就应该去实现吧)
|
||||
// 叠层
|
||||
{
|
||||
// 开始尝试叠层
|
||||
uint16_t tmp = 0;
|
||||
uint16_t p_w, p_h;
|
||||
struct yuv_arg_s *yuv_msg = NULL;
|
||||
while (tmp < sim_video->screen_num)
|
||||
{
|
||||
if (sim_video->screen[tmp])
|
||||
{
|
||||
yuv_msg = (struct yuv_arg_s *)sim_video->screen[tmp]->priv;
|
||||
p_w = yuv_msg->out_w;
|
||||
p_h = yuv_msg->out_h;
|
||||
|
||||
|
||||
yuv_blk_cpy((uint8_t*)output_fb->data, sim_video->screen[tmp]->data, sim_video->w, sim_video->h, p_w, p_h, yuv_msg->x, yuv_msg->y);
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
output_fb->mtype = F_YUV;
|
||||
output_fb->stype = FSTYPE_YUV_P0;
|
||||
msi_output_fb(sim_video->msi, output_fb);
|
||||
}
|
||||
}
|
||||
sim_video_work_end:
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int32 sim_video_more_work_more(struct os_work *work)
|
||||
{
|
||||
#define REFRESH_LCD_INTERNAL_TIME 10
|
||||
struct sim_video_more_msi_s *sim_video = (struct sim_video_more_msi_s *)work;
|
||||
struct framebuff *fb;
|
||||
struct framebuff *output_fb;
|
||||
|
||||
static uint16_t oldbigx,oldbigy;
|
||||
uint32_t dispbuf;
|
||||
uint32_t *cache_buf[10];
|
||||
uint8_t push_lcd_updata=0;
|
||||
uint8_t display_only = 0;
|
||||
uint16_t p_w, p_h;
|
||||
uint16_t max_w;
|
||||
uint16_t tmp = 0;
|
||||
struct yuv_arg_s *yuv_msg = NULL;
|
||||
struct app_lcd_s *lcd_s = &lcd_msg_s;
|
||||
|
||||
output_fb = NULL;
|
||||
|
||||
if(sim_video->last_input_fb != NULL){
|
||||
fb = sim_video->last_input_fb;
|
||||
}else{
|
||||
fb = msi_get_fb(sim_video->msi, 0);
|
||||
}
|
||||
// 接收到一个fb,就需要判断类型(p0,p1),然后申请空间去进行叠层
|
||||
if (fb)
|
||||
{
|
||||
// 查看类型是否匹配(正常到这里一定匹配,因为接收的时候就进行过滤了)
|
||||
uint16_t match_count = 0;
|
||||
uint8_t match_flag = 0;
|
||||
while (match_count < sim_video->screen_num)
|
||||
{
|
||||
if (fb->stype == sim_video->filter[match_count]) //类型检查,看一下当前的fb类型是否存在于过滤网内
|
||||
{
|
||||
yuv_msg = (struct yuv_arg_s *)fb->priv;
|
||||
if(sim_video->subwindow_cnt[match_count] != sim_video->dispwindow_cnt[match_count]){ //重复更新,当前要刷的叠层已在备刷区,但又来了新的数据,那要把备刷区推出去
|
||||
push_lcd_updata = 1;
|
||||
sim_video->last_input_fb = fb;
|
||||
output_fb = sim_video->last_fb;
|
||||
goto sim_video_push_lcd;
|
||||
}
|
||||
match_flag = 1;
|
||||
break;
|
||||
}
|
||||
match_count++;
|
||||
}
|
||||
|
||||
// 没有匹配,删除,并且不需要刷新
|
||||
if (!match_flag)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
if(fb == sim_video->last_input_fb) {
|
||||
sim_video->last_input_fb = NULL;
|
||||
}
|
||||
fb = NULL;
|
||||
goto sim_video_work_end;
|
||||
}
|
||||
|
||||
if(sim_video->lcd_fb_updata){
|
||||
sim_video->lcd_fb_updata = 0;
|
||||
sim_video->last_input_fb = fb;
|
||||
|
||||
output_fb = fbpool_get(&sim_video->tx_pool, 0, sim_video->msi); //从sim_video的发送池里找到对应的fb
|
||||
if(!output_fb){ //需要更新时无法申请到fb,则下次重新申请,直到能申请为止
|
||||
sim_video->lcd_fb_updata = 1;
|
||||
goto sim_video_work_end;
|
||||
}else{ //申请到了,表示当前input_fb可被处理掉,指针清空一下
|
||||
if((uint32_t)output_fb->data == sim_video->bufadr[0]){
|
||||
dispbuf = sim_video->bufadr[1]; //提取当前正在显示的buf地址,用来拷数据
|
||||
}else{
|
||||
dispbuf = sim_video->bufadr[0];
|
||||
}
|
||||
//hw_memcpy(output_fb->data,dispbuf,output_fb->len);
|
||||
yuv_blk_cpy((uint8_t*)output_fb->data, (uint8_t*)dispbuf, sim_video->w, sim_video->h, sim_video->w,sim_video->h, 0,0);
|
||||
sim_video->last_input_fb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!output_fb)
|
||||
{
|
||||
output_fb = sim_video->last_fb;
|
||||
}else{
|
||||
sim_video->last_fb = output_fb; //记录当前要修改的fb
|
||||
}
|
||||
|
||||
|
||||
sim_video->subwindow_cnt[match_count] = yuv_msg->dispcnt;
|
||||
sim_video->dsp_window_msg[match_count].w = yuv_msg->out_w;
|
||||
sim_video->dsp_window_msg[match_count].h = yuv_msg->out_h;
|
||||
sim_video->dsp_window_msg[match_count].x = yuv_msg->x;
|
||||
sim_video->dsp_window_msg[match_count].y = yuv_msg->y;
|
||||
sim_video->video_display_mask[match_count] = yuv_msg->video_only;
|
||||
|
||||
if((uint32_t)output_fb->data == sim_video->bufadr[0]){
|
||||
dispbuf = sim_video->bufadr[1]; //提取当前正在显示的buf地址,用来拷数据
|
||||
}else{
|
||||
dispbuf = sim_video->bufadr[0];
|
||||
}
|
||||
|
||||
display_only = 0;
|
||||
tmp = 0;
|
||||
while (tmp < sim_video->screen_num) { //选出是否配置独显了
|
||||
if(sim_video->video_display_mask[tmp] != 0){
|
||||
if(yuv_msg->video_only){ //当前数据流是否就是要显示的数据流
|
||||
display_only |= BIT(7);
|
||||
}
|
||||
display_only++;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
|
||||
if((display_only&0x7f) > 1){
|
||||
_os_printf("too much stream set display only mode\r\n");
|
||||
}
|
||||
|
||||
|
||||
max_w = 0;
|
||||
tmp = 0;
|
||||
while (tmp < sim_video->screen_num) { //选出最大的图片
|
||||
if(sim_video->dsp_window_msg[tmp].w > max_w){
|
||||
max_w = sim_video->dsp_window_msg[tmp].w;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
|
||||
yuv_msg = (struct yuv_arg_s *)fb->priv;
|
||||
p_w = yuv_msg->out_w;
|
||||
p_h = yuv_msg->out_h;
|
||||
|
||||
if(display_only){ //有设备打开了独显
|
||||
if((display_only&BIT(7)) == BIT(7)){
|
||||
hw_memset((uint8_t*)output_fb->data, 0, sim_video->w * sim_video->h); //清黑屏
|
||||
hw_memset((uint8_t*)output_fb->data + sim_video->w * sim_video->h, 0x80, sim_video->w * sim_video->h / 2);
|
||||
yuv_blk_cpy((uint8_t*)output_fb->data, fb->data, sim_video->w, sim_video->h, p_w, p_h, yuv_msg->x, yuv_msg->y); //把大图拷好
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(max_w != yuv_msg->out_w){ //如果并非大图
|
||||
yuv_blk_cpy((uint8_t*)output_fb->data, fb->data, sim_video->w, sim_video->h, p_w, p_h, yuv_msg->x, yuv_msg->y); //拷到对应的位置上
|
||||
}else{ //如果是大图
|
||||
tmp = 0;
|
||||
while(tmp < sim_video->screen_num){
|
||||
cache_buf[tmp] = NULL;
|
||||
if( (match_count != tmp) && (sim_video->dsp_window_msg[tmp].w != 0)){
|
||||
if(sim_video->subwindow_cnt[tmp] > sim_video->dispwindow_cnt[tmp]){ //如果备用区数值是更新的,那就拷出来
|
||||
cache_buf[tmp] = (uint32_t *)STREAM_MALLOC(sim_video->dsp_window_msg[tmp].w * sim_video->dsp_window_msg[tmp].h * 3 / 2); //申请小图空间
|
||||
sys_dcache_invalid_range(cache_buf[tmp], sim_video->dsp_window_msg[tmp].w * sim_video->dsp_window_msg[tmp].h * 3 / 2);
|
||||
if(cache_buf[tmp] != NULL){
|
||||
yuv_blk_reduce((uint8_t*)cache_buf[tmp],(uint8_t*)output_fb->data,sim_video->dsp_window_msg[tmp].w,sim_video->dsp_window_msg[tmp].h,sim_video->w,sim_video->h,sim_video->dsp_window_msg[tmp].x,sim_video->dsp_window_msg[tmp].y);
|
||||
}else{
|
||||
_os_printf("malloc psram for sim video error1\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
|
||||
if((oldbigx != yuv_msg->x) || (oldbigy != yuv_msg->y)){
|
||||
hw_memset((uint8_t*)output_fb->data, 0, sim_video->w * sim_video->h); //大图产生偏移,清黑屏
|
||||
hw_memset((uint8_t*)output_fb->data + sim_video->w * sim_video->h, 0x80, sim_video->w * sim_video->h / 2);
|
||||
}
|
||||
|
||||
yuv_blk_cpy((uint8_t*)output_fb->data, fb->data, sim_video->w, sim_video->h, p_w, p_h, yuv_msg->x, yuv_msg->y); //把大图拷好
|
||||
oldbigx = yuv_msg->x;
|
||||
oldbigy = yuv_msg->y;
|
||||
|
||||
tmp = 0;
|
||||
while(tmp < sim_video->screen_num){
|
||||
if( (match_count != tmp) && (sim_video->dsp_window_msg[tmp].w != 0)){
|
||||
if(cache_buf[tmp]){ //图片是从之前的备用区提取出来的,在缓存中
|
||||
yuv_blk_cpy((uint8_t*)output_fb->data, (uint8_t*)cache_buf[tmp], sim_video->w, sim_video->h, sim_video->dsp_window_msg[tmp].w,sim_video->dsp_window_msg[tmp].h, sim_video->dsp_window_msg[tmp].x,sim_video->dsp_window_msg[tmp].y); //拷到对应的psram块中
|
||||
STREAM_FREE((uint8_t*)cache_buf[tmp]);
|
||||
}
|
||||
else{ //图片得从刷新区那里提取
|
||||
cache_buf[tmp] = (uint32_t *)STREAM_MALLOC(sim_video->dsp_window_msg[tmp].w * sim_video->dsp_window_msg[tmp].h * 3 / 2);
|
||||
sys_dcache_invalid_range(cache_buf[tmp],sim_video->dsp_window_msg[tmp].w * sim_video->dsp_window_msg[tmp].h * 3 / 2);
|
||||
if(cache_buf[tmp] != NULL){
|
||||
yuv_blk_reduce((uint8_t*)cache_buf[tmp],(uint8_t*)dispbuf,sim_video->dsp_window_msg[tmp].w,sim_video->dsp_window_msg[tmp].h,sim_video->w,sim_video->h,sim_video->dsp_window_msg[tmp].x,sim_video->dsp_window_msg[tmp].y);
|
||||
yuv_blk_cpy((uint8_t*)output_fb->data, (uint8_t*)cache_buf[tmp], sim_video->w, sim_video->h, sim_video->dsp_window_msg[tmp].w,sim_video->dsp_window_msg[tmp].h, sim_video->dsp_window_msg[tmp].x,sim_video->dsp_window_msg[tmp].y);
|
||||
STREAM_FREE((uint8_t*)cache_buf[tmp]);
|
||||
}else{
|
||||
_os_printf("malloc psram for sim video error2\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
sim_video_push_lcd:
|
||||
if(push_lcd_updata == 1){
|
||||
|
||||
memcpy(sim_video->dispwindow_cnt,sim_video->subwindow_cnt,10*4);
|
||||
output_fb->mtype = F_YUV;
|
||||
output_fb->stype = FSTYPE_YUV_P0;
|
||||
msi_output_fb(sim_video->msi, output_fb); //将当前推屏的fb推出去
|
||||
sim_video->lcd_fb_updata = 1; //下次提取新的刷屏帧
|
||||
sim_video->last_fb = NULL;
|
||||
}else{
|
||||
msi_delete_fb(NULL, fb); //删除对应的输入到msi video的fb
|
||||
fb = NULL;
|
||||
}
|
||||
}
|
||||
sim_video_work_end:
|
||||
if((os_jiffies() - lcd_s->start_time) > (lcd_s->refresh_time - REFRESH_LCD_INTERNAL_TIME)){ //当距离结束刷屏时间为REFRESH_LCD_INTERNAL_TIME时,检查是否需要更新,需要的话,就先更新
|
||||
if(output_fb){ //先检查推屏的fb是否存在
|
||||
tmp = 0;
|
||||
while(tmp < sim_video->screen_num){ //检查各个叠层
|
||||
if(sim_video->dispwindow_cnt[tmp] != sim_video->subwindow_cnt[tmp]){ //发现有叠层出现更新了
|
||||
memcpy(sim_video->dispwindow_cnt,sim_video->subwindow_cnt,10*4);
|
||||
output_fb->mtype = F_YUV;
|
||||
output_fb->stype = FSTYPE_YUV_P0;
|
||||
msi_output_fb(sim_video->msi, output_fb); //将当前推屏的fb推出去
|
||||
sim_video->lcd_fb_updata = 1; //下次提取新的刷屏帧
|
||||
sim_video->last_fb = NULL;
|
||||
break;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sim_video_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
struct sim_video_more_msi_s *sim_video = (struct sim_video_more_msi_s *)msi->priv;
|
||||
int ret = RET_OK;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
struct framebuff *fb;
|
||||
// 释放资源fb资源文件,priv是独立申请的
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&sim_video->tx_pool, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&sim_video->tx_pool);
|
||||
STREAM_LIBC_FREE(sim_video);
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
|
||||
if (fb->mtype != F_YUV)
|
||||
{
|
||||
// os_printf("not recv fb:%X\tcount:%d\n",fb,fb->users.counter);
|
||||
ret = RET_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sim_video->filter)
|
||||
{
|
||||
// 轮询类型是否有一致
|
||||
ret = RET_ERR;
|
||||
uint16_t *each = sim_video->filter;
|
||||
while (*each)
|
||||
{
|
||||
// 如果一致,返回OK
|
||||
if (*each == fb->stype)
|
||||
{
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
each++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
// 如果不是克隆的,就自己释放
|
||||
if (!fb->clone)
|
||||
{
|
||||
// if (fb->data)
|
||||
// {
|
||||
// STREAM_FREE(fb->data);
|
||||
// fb->data = NULL;
|
||||
// }
|
||||
fbpool_put(&sim_video->tx_pool, fb);
|
||||
// 不需要内核去释放fb
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&sim_video->work, 1);
|
||||
uint16_t tmp = 0;
|
||||
while (tmp < sim_video->screen_num)
|
||||
{
|
||||
if (sim_video->screen[tmp])
|
||||
{
|
||||
msi_delete_fb(NULL, sim_video->screen[tmp]);
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct framebuff *fb = msi_get_fb(msi, 0);
|
||||
if (fb) {
|
||||
msi_delete_fb(NULL, fb);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sim_video->last_fb){
|
||||
msi_delete_fb(NULL, sim_video->last_fb);
|
||||
sim_video->last_fb = NULL;
|
||||
}
|
||||
|
||||
if(sim_video->last_input_fb){
|
||||
msi_delete_fb(NULL, sim_video->last_input_fb);
|
||||
sim_video->last_input_fb = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *sim_video_more_msi(const char *name, uint16_t w, uint16_t h, uint16_t *sim_filter)
|
||||
{
|
||||
// 设置1个接收,只是为了可以output_fb给到这个msi
|
||||
uint16_t count = 0;
|
||||
uint32_t *buf;
|
||||
struct msi *msi = msi_new(name, MAX_RX, NULL);
|
||||
if (msi)
|
||||
{
|
||||
struct sim_video_more_msi_s *sim_video = (struct sim_video_more_msi_s *)msi->priv;
|
||||
if (!sim_video)
|
||||
{
|
||||
// 统计sim_filter数量来决定screen的数量
|
||||
|
||||
while (*(sim_filter + count))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
sim_video = (struct sim_video_more_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct sim_video_more_msi_s) + (sizeof(struct framebuff *) * count));
|
||||
}
|
||||
|
||||
sim_video->w = w;
|
||||
sim_video->h = h;
|
||||
sim_video->msi = msi;
|
||||
sim_video->filter = sim_filter;
|
||||
sim_video->screen_num = count;
|
||||
// 申请空间的时候就已经多申请了,所有screen放在末尾
|
||||
sim_video->screen = (struct framebuff **)(sim_video + 1);
|
||||
sim_video->lcd_fb_updata = 1;
|
||||
msi->priv = (void *)sim_video;
|
||||
msi->action = sim_video_msi_action;
|
||||
|
||||
// 预分配结构体空间
|
||||
uint32_t init_count = 0;
|
||||
void *priv;
|
||||
fbpool_init(&sim_video->tx_pool, MAX_TX);
|
||||
while (init_count < MAX_TX)
|
||||
{
|
||||
priv = (void *)STREAM_LIBC_ZALLOC(sizeof(struct yuv_arg_s));
|
||||
struct yuv_arg_s *yuv_msg = (struct yuv_arg_s *)priv;
|
||||
buf = (uint32_t *)STREAM_MALLOC(sim_video->w * sim_video->h * 3 / 2);
|
||||
hw_memset((uint8_t*)buf, 0, sim_video->w * sim_video->h); //清空整个空间,将显示背景显示全黑
|
||||
hw_memset((uint8_t*)buf + sim_video->w * sim_video->h, 0x80, sim_video->w * sim_video->h / 2);
|
||||
sys_dcache_invalid_range(buf, sim_video->w * sim_video->h * 3 / 2); //清cache
|
||||
yuv_msg->out_w = w;
|
||||
yuv_msg->out_h = h;
|
||||
yuv_msg->y_size = w * h;
|
||||
yuv_msg->y_off = 0;
|
||||
yuv_msg->uv_off = 0;
|
||||
yuv_msg->del = NULL;
|
||||
sim_video->bufadr[init_count] = (uint32_t)buf;
|
||||
FBPOOL_SET_INFO(&sim_video->tx_pool, init_count, (uint8_t*)buf, sim_video->w * sim_video->h * 3 / 2, priv);
|
||||
init_count++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
msi->enable = 1;
|
||||
|
||||
// msi_add_output(sim_video->msi, NULL, R_VIDEO_P0);
|
||||
|
||||
OS_WORK_INIT(&sim_video->work, sim_video_more_work_more, 0);
|
||||
os_run_work_delay(&sim_video->work, 1);
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
316
sdk/app/app_lcd/sim_video_msi.c
Normal file
316
sdk/app/app_lcd/sim_video_msi.c
Normal file
@@ -0,0 +1,316 @@
|
||||
/**********************************************************************************************************
|
||||
* 虚拟的P0和P1,使用dma2d去实现p0和p1的叠层,最终目的是为了让lcd不旋转(省sram),直接预先旋转叠层给到video显示
|
||||
* ********************************************************************************************************/
|
||||
#include "basic_include.h"
|
||||
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "osal/work.h"
|
||||
#include "stream_define.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
|
||||
|
||||
extern void yuv_blk_cpy(uint8 *des, uint8* src,uint32 des_w,uint32 des_h, uint32 src_w, uint32_t src_h,uint32 x,uint32 y);
|
||||
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define MAX_RX 8
|
||||
|
||||
struct sim_video_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct fbpool tx_pool;
|
||||
struct framebuff *p0;
|
||||
struct framebuff *p1;
|
||||
uint16_t w, h;
|
||||
uint16_t *filter; //数组去进行过滤,0为结束
|
||||
// 设置哪个在顶层,这个模块只有P0和P1
|
||||
uint8_t top;
|
||||
};
|
||||
|
||||
static int32 sim_video_work(struct os_work *work)
|
||||
{
|
||||
struct sim_video_msi_s *sim_video = (struct sim_video_msi_s *)work;
|
||||
struct framebuff *fb;
|
||||
struct framebuff *output_fb;
|
||||
uint32_t *buf;
|
||||
fb = msi_get_fb(sim_video->msi, 0);
|
||||
// 接收到一个fb,就需要判断类型(p0,p1),然后申请空间去进行叠层
|
||||
if (fb)
|
||||
{
|
||||
if (fb->stype == FSTYPE_YUV_P0)
|
||||
{
|
||||
if (sim_video->p0)
|
||||
{
|
||||
msi_delete_fb(NULL, sim_video->p0);
|
||||
}
|
||||
sim_video->p0 = fb;
|
||||
}
|
||||
else if (fb->stype == FSTYPE_YUV_P1)
|
||||
{
|
||||
if (sim_video->p1)
|
||||
{
|
||||
msi_delete_fb(NULL, sim_video->p1);
|
||||
}
|
||||
sim_video->p1 = fb;
|
||||
}
|
||||
else
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
goto sim_video_work_end;
|
||||
}
|
||||
|
||||
// 不需要叠层,帮忙转发就好了,但是需要保留p0或者p1
|
||||
// 因为output会发送完毕后会执行删除,所以要保留,不能被删除
|
||||
if (fb && !(sim_video->p0 && sim_video->p1))
|
||||
{
|
||||
// 克隆一个fb发出去,但是因为这个sim_video是给到P0显示,所以需要将stype转换成FSTYPE_YUV_P0
|
||||
output_fb = fb_clone(fb, fb->mtype<<8|FSTYPE_YUV_P0, sim_video->msi);
|
||||
if (output_fb)
|
||||
{
|
||||
msi_output_fb(sim_video->msi, output_fb);
|
||||
}
|
||||
|
||||
goto sim_video_work_end;
|
||||
}
|
||||
//os_printf("sim video p0:%X\tp1:%X\n",sim_video->p0,sim_video->p1);
|
||||
// 开始申请空间
|
||||
buf = (uint32_t *)STREAM_MALLOC(sim_video->w * sim_video->h * 3 / 2);
|
||||
if (!buf)
|
||||
{
|
||||
goto sim_video_work_end;
|
||||
}
|
||||
|
||||
output_fb = fbpool_get(&sim_video->tx_pool, 0, sim_video->msi);
|
||||
if (!output_fb)
|
||||
{
|
||||
STREAM_FREE(buf);
|
||||
goto sim_video_work_end;
|
||||
}
|
||||
output_fb->data = (uint8_t*)buf;
|
||||
output_fb->len = sim_video->w * sim_video->h * 3 / 2;
|
||||
|
||||
// 叠层
|
||||
{
|
||||
uint16_t p0_w= 0, p0_h = 0, p1_w = 0, p1_h = 0;
|
||||
struct yuv_arg_s *yuv_msg_p0 = NULL;
|
||||
struct yuv_arg_s *yuv_msg_p1 = NULL;
|
||||
if (sim_video->p0)
|
||||
{
|
||||
yuv_msg_p0 = (struct yuv_arg_s *)sim_video->p0->priv;
|
||||
p0_w = yuv_msg_p0->out_w;
|
||||
p0_h = yuv_msg_p0->out_h;
|
||||
}
|
||||
if (sim_video->p1)
|
||||
{
|
||||
yuv_msg_p1 = (struct yuv_arg_s *)sim_video->p1->priv;
|
||||
p1_w = yuv_msg_p1->out_w;
|
||||
p1_h = yuv_msg_p1->out_h;
|
||||
}
|
||||
|
||||
// 判断一下p0_w和p1_w是否和当前的w,h匹配,不匹配,可能底部需要配置颜色才可以
|
||||
uint16_t p_w = p0_w > p1_w ? p0_w : p1_w;
|
||||
uint16_t p_h = p0_h > p1_h ? p0_h : p1_h;
|
||||
// 如果没有匹配,设置颜色
|
||||
if (!(p_w >= sim_video->w && p_h >= sim_video->h))
|
||||
{
|
||||
hw_memset((uint8_t*)buf, 0, sim_video->w * sim_video->h);
|
||||
hw_memset((uint8_t*)buf+sim_video->w * sim_video->h,0x80,sim_video->w * sim_video->h / 2);
|
||||
sys_dcache_invalid_range(buf, sim_video->w * sim_video->h * 3 / 2);
|
||||
}
|
||||
|
||||
|
||||
//os_printf("yuv_msg_p1->x:%d\ty:%d\n",yuv_msg_p1->x,yuv_msg_p1->y);
|
||||
//os_printf("yuv_msg_p0->x:%d\ty:%d\n",yuv_msg_p0->x,yuv_msg_p0->y);
|
||||
if (sim_video->top == 0)
|
||||
{
|
||||
|
||||
if (yuv_msg_p1)
|
||||
{
|
||||
yuv_blk_cpy((uint8_t*)buf, sim_video->p1->data, sim_video->w, sim_video->h, p1_w, p1_h, yuv_msg_p1->x, yuv_msg_p1->y);
|
||||
}
|
||||
if (yuv_msg_p0)
|
||||
{
|
||||
yuv_blk_cpy((uint8_t*)buf, sim_video->p0->data, sim_video->w, sim_video->h, p0_w, p0_h, yuv_msg_p0->x, yuv_msg_p0->y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (yuv_msg_p0)
|
||||
{
|
||||
yuv_blk_cpy((uint8_t*)buf, sim_video->p0->data, sim_video->w, sim_video->h, p0_w, p0_h, yuv_msg_p0->x, yuv_msg_p0->y);
|
||||
}
|
||||
|
||||
if (yuv_msg_p1)
|
||||
{
|
||||
yuv_blk_cpy((uint8_t*)buf, sim_video->p1->data, sim_video->w, sim_video->h, p1_w, p1_h, yuv_msg_p1->x, yuv_msg_p1->y);
|
||||
}
|
||||
}
|
||||
output_fb->mtype = F_YUV;
|
||||
output_fb->stype = FSTYPE_YUV_P0;
|
||||
msi_output_fb(sim_video->msi, output_fb);
|
||||
}
|
||||
}
|
||||
sim_video_work_end:
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
static int sim_video_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
struct sim_video_msi_s *sim_video = (struct sim_video_msi_s *)msi->priv;
|
||||
int ret = RET_OK;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
struct framebuff *fb;
|
||||
// 释放资源fb资源文件,priv是独立申请的
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&sim_video->tx_pool, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&sim_video->tx_pool);
|
||||
STREAM_LIBC_FREE(sim_video);
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
|
||||
if (fb->mtype != F_YUV)
|
||||
{
|
||||
//os_printf("not recv fb:%X\tcount:%d\n",fb,fb->users.counter);
|
||||
ret = RET_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sim_video->filter)
|
||||
{
|
||||
//轮询类型是否有一致
|
||||
ret = RET_ERR;
|
||||
uint16_t *each = sim_video->filter;
|
||||
while(*each)
|
||||
{
|
||||
//如果一致,返回OK
|
||||
if(*each == fb->stype)
|
||||
{
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
each++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
// 如果不是克隆的,就自己释放
|
||||
if (!fb->clone)
|
||||
{
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
fbpool_put(&sim_video->tx_pool, fb);
|
||||
// 不需要内核去释放fb
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&sim_video->work, 1);
|
||||
if (sim_video->p0)
|
||||
{
|
||||
msi_delete_fb(NULL, sim_video->p0);
|
||||
sim_video->p0 = NULL;
|
||||
}
|
||||
if (sim_video->p1)
|
||||
{
|
||||
msi_delete_fb(NULL, sim_video->p1);
|
||||
sim_video->p1 = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *sim_video_msi(const char *name, uint16_t w, uint16_t h, uint8_t top)
|
||||
{
|
||||
static const uint16_t sim_filter[3] = {FSTYPE_YUV_P0,FSTYPE_YUV_P1,FSTYPE_NONE};
|
||||
// 设置1个接收,只是为了可以output_fb给到这个msi
|
||||
struct msi *msi = msi_new(name, MAX_RX, NULL);
|
||||
if (msi)
|
||||
{
|
||||
struct sim_video_msi_s *sim_video = (struct sim_video_msi_s *)msi->priv;
|
||||
if (!sim_video)
|
||||
{
|
||||
sim_video = (struct sim_video_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct sim_video_msi_s));
|
||||
}
|
||||
sim_video->p0 = NULL;
|
||||
sim_video->p1 = NULL;
|
||||
sim_video->w = w;
|
||||
sim_video->h = h;
|
||||
sim_video->msi = msi;
|
||||
sim_video->filter = (uint16_t*)sim_filter;
|
||||
sim_video->top = top;
|
||||
msi->priv = (void *)sim_video;
|
||||
msi->action = sim_video_msi_action;
|
||||
|
||||
// 预分配结构体空间
|
||||
uint32_t init_count = 0;
|
||||
void *priv;
|
||||
fbpool_init(&sim_video->tx_pool, MAX_RX);
|
||||
while (init_count < MAX_RX)
|
||||
{
|
||||
priv = (void *)STREAM_LIBC_ZALLOC(sizeof(struct yuv_arg_s));
|
||||
struct yuv_arg_s *yuv_msg = (struct yuv_arg_s *)priv;
|
||||
yuv_msg->out_w = w;
|
||||
yuv_msg->out_h = h;
|
||||
yuv_msg->y_size = w * h;
|
||||
yuv_msg->y_off = 0;
|
||||
yuv_msg->uv_off = 0;
|
||||
yuv_msg->del = NULL;
|
||||
FBPOOL_SET_INFO(&sim_video->tx_pool, init_count, NULL, 0, priv);
|
||||
init_count++;
|
||||
}
|
||||
|
||||
msi->enable = 1;
|
||||
|
||||
//msi_add_output(sim_video->msi, NULL, R_VIDEO_P0);
|
||||
|
||||
OS_WORK_INIT(&sim_video->work, sim_video_work, 0);
|
||||
os_run_work_delay(&sim_video->work, 1);
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
27
sdk/app/audio_media_ctrl/aac/aac_code.h
Normal file
27
sdk/app/audio_media_ctrl/aac/aac_code.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef _AAC_CODE_H_
|
||||
#define _AAC_CODE_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "audio_code_ctrl.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define AAC_CODE_MALLOC av_psram_malloc
|
||||
#define AAC_CODE_ZALLOC av_psram_zalloc
|
||||
#define AAC_CODE_CALLOC av_psram_calloc
|
||||
#define AAC_CODE_FREE av_psram_free
|
||||
#else
|
||||
#define AAC_CODE_MALLOC av_malloc
|
||||
#define AAC_CODE_ZALLOC av_zalloc
|
||||
#define AAC_CODE_CALLOC av_calloc
|
||||
#define AAC_CODE_FREE av_free
|
||||
#endif
|
||||
|
||||
#define AAC_DEBUG(fmt, args...) //os_printf(fmt, ##args)
|
||||
#define AAC_INFO os_printf
|
||||
|
||||
struct msi *aac_encode_init(char *filename, uint32_t samplerate, uint8_t direct_to_record, AUENC_INIT *auenc_init);
|
||||
struct msi *aac_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init);
|
||||
|
||||
#endif
|
||||
584
sdk/app/audio_media_ctrl/aac/aac_decode.c
Normal file
584
sdk/app/audio_media_ctrl/aac/aac_decode.c
Normal file
@@ -0,0 +1,584 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/audio/audio_code/audio_code.h"
|
||||
#include "autpc_msi/autpc_msi.h"
|
||||
#include "osal_file.h"
|
||||
#include "aac_code.h"
|
||||
|
||||
#define BUFF_SIZE 2048
|
||||
#define MAX_AAC_DECODE_RXBUF 4
|
||||
#define MAX_AAC_DECODE_TXBUF 4
|
||||
|
||||
struct aac_decode_struct {
|
||||
AUDIO_TRACK audio_track;
|
||||
struct fbpool tx_pool;
|
||||
struct os_event event;
|
||||
struct msi *msi;
|
||||
struct msi *src_msi;
|
||||
struct msi *autpc_msi;
|
||||
char *msi_name;
|
||||
void *task_hdl;
|
||||
void *aac_fp;
|
||||
uint8_t loop_mode;
|
||||
uint8_t direct_to_dac;
|
||||
uint8_t use_tpc;
|
||||
uint8_t speed;
|
||||
uint8_t pitch;
|
||||
uint8_t destroy_self;
|
||||
uint8_t next_status;
|
||||
uint8_t current_status;
|
||||
uint8_t inbuf[BUFF_SIZE];
|
||||
int16_t dec_buf[1024*2];
|
||||
};
|
||||
|
||||
static int32_t aac_file_read(struct aac_decode_struct *aac_decode_s, uint8_t *buf, uint32_t size)
|
||||
{
|
||||
int32_t read_len = 0;
|
||||
|
||||
read_len = osal_fread(buf, size, 1, aac_decode_s->aac_fp);
|
||||
return read_len;
|
||||
}
|
||||
|
||||
static void aac_file_decode(struct aac_decode_struct *s)
|
||||
{
|
||||
uint8_t endOfRead = 0;
|
||||
uint8_t *enc_ptr = NULL;
|
||||
int16_t *data = NULL;
|
||||
int32_t ret = 0;
|
||||
int32_t read_len = 0;
|
||||
int32_t dec_samples = 0;
|
||||
int32_t unproc_data_size = 0;
|
||||
uint32_t enc_ptr_offset = 0;
|
||||
uint32_t bytes_to_read = 0;
|
||||
uint32_t interval_time = 0;
|
||||
struct framebuff *frame_buf = NULL;
|
||||
AUCODE_HDL *aac_dec = NULL;
|
||||
AUCODE_FRAME_INFO aac_info;
|
||||
AUDIO_TRACK *audac_fiter_track = NULL;
|
||||
|
||||
aac_dec = audio_coder_open(AAC_DEC, 0, 0);
|
||||
if(!aac_dec)
|
||||
return;
|
||||
enc_ptr = s->inbuf;
|
||||
while(1) {
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
while(s->next_status == AUCODEC_PAUSE) {
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
goto aac_decode_end;
|
||||
}
|
||||
s->current_status = AUCODEC_RUN;
|
||||
|
||||
if(unproc_data_size < 1536 && !endOfRead) {
|
||||
bytes_to_read = BUFF_SIZE - unproc_data_size;
|
||||
if(unproc_data_size)
|
||||
os_memcpy(s->inbuf, enc_ptr+enc_ptr_offset, unproc_data_size);
|
||||
read_len = aac_file_read(s, s->inbuf+unproc_data_size, bytes_to_read);
|
||||
if(read_len <= 0) {
|
||||
AAC_INFO("aac read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
|
||||
endOfRead = 1;
|
||||
}
|
||||
else
|
||||
unproc_data_size += read_len;
|
||||
enc_ptr = s->inbuf;
|
||||
enc_ptr_offset = 0;
|
||||
}
|
||||
|
||||
if(unproc_data_size > 0) {
|
||||
while(!frame_buf) {
|
||||
frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(!frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
data = (int16_t*)frame_buf->data;
|
||||
dec_samples = audio_decode_data(aac_dec, enc_ptr+enc_ptr_offset, unproc_data_size, s->dec_buf, &aac_info);
|
||||
if(dec_samples <= 0) {
|
||||
enc_ptr_offset += 1;
|
||||
unproc_data_size -= 1;
|
||||
msi_delete_fb(s->msi, frame_buf);
|
||||
frame_buf = NULL;
|
||||
continue;
|
||||
}
|
||||
if(aac_info.channels == 2) {
|
||||
for(uint32_t i=0; i<dec_samples; i++)
|
||||
data[i] = s->dec_buf[2*i];
|
||||
}
|
||||
else {
|
||||
for(uint32_t i=0; i<dec_samples; i++)
|
||||
data[i] = s->dec_buf[i];
|
||||
}
|
||||
enc_ptr_offset += aac_info.frame_bytes;
|
||||
unproc_data_size -= aac_info.frame_bytes;
|
||||
frame_buf->len = dec_samples*2;
|
||||
frame_buf->mtype = F_AUDIO;
|
||||
frame_buf->stype = FSTYPE_AUDIO_PCM;
|
||||
s->audio_track.samplerate = aac_info.samplerate;
|
||||
if(s->use_tpc && !s->autpc_msi) {
|
||||
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
|
||||
if(s->autpc_msi == NULL) {
|
||||
goto aac_decode_end;
|
||||
}
|
||||
if(s->direct_to_dac) {
|
||||
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_add_output(s->msi, NULL, s->autpc_msi->name);
|
||||
}
|
||||
ret = msi_output_fb(s->msi, frame_buf);
|
||||
AAC_DEBUG("aac decode send framebuff:%p,ret:%d\r\n",frame_buf,ret);
|
||||
msi_cmd("R_AUDAC", MSI_CMD_AUDAC, MSI_AUDAC_GET_FILTER_TRACK, (uint32_t)(&audac_fiter_track));
|
||||
if(s->direct_to_dac && (!s->use_tpc) && (audac_fiter_track != (&(s->audio_track)))) {
|
||||
interval_time = (frame_buf->len>>1)*1000/(aac_info.samplerate);
|
||||
os_sleep_ms(interval_time);
|
||||
}
|
||||
frame_buf = NULL;
|
||||
}
|
||||
else if(endOfRead) {
|
||||
goto aac_decode_end;
|
||||
}
|
||||
}
|
||||
aac_decode_end:
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
if(frame_buf) {
|
||||
msi_delete_fb(s->msi, frame_buf);
|
||||
frame_buf = NULL;
|
||||
}
|
||||
if(aac_dec)
|
||||
audio_coder_close(aac_dec);
|
||||
}
|
||||
|
||||
static void aac_msi_decode(struct aac_decode_struct *s)
|
||||
{
|
||||
uint8_t clear_finish = 1;
|
||||
uint8_t *enc_ptr = NULL;
|
||||
int16_t *send_data = NULL;
|
||||
int32_t ret = 0;
|
||||
int32_t data_len = 0;
|
||||
int32_t dec_samples = 0;
|
||||
uint32_t clear_flag = 0;
|
||||
struct framebuff *recv_frame_buf = NULL;
|
||||
struct framebuff *send_frame_buf = NULL;
|
||||
AUCODE_HDL *aac_dec = NULL;
|
||||
AUCODE_FRAME_INFO aac_info;
|
||||
|
||||
aac_dec = audio_coder_open(AAC_DEC, 0, 1);
|
||||
if(!aac_dec)
|
||||
return;
|
||||
while(1) {
|
||||
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
|
||||
if(clear_flag & coder_clear_event) {
|
||||
clear_flag = 0;
|
||||
clear_finish = 0;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
aac_dec = audio_coder_open(AAC_DEC, 0, 1);
|
||||
if(!aac_dec)
|
||||
return;
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
}
|
||||
recv_frame_buf = msi_get_fb(s->msi, 0);
|
||||
if(recv_frame_buf) {
|
||||
if(clear_finish == 0) {
|
||||
goto aac_decode_frame_end;
|
||||
}
|
||||
if(s->current_status == AUCODEC_PAUSE) {
|
||||
goto aac_decode_frame_end;
|
||||
}
|
||||
else {
|
||||
s->current_status = AUCODEC_RUN;
|
||||
while(!send_frame_buf) {
|
||||
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(!send_frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
data_len = recv_frame_buf->len;
|
||||
if(data_len > 0) {
|
||||
enc_ptr = recv_frame_buf->data;
|
||||
dec_samples = audio_decode_data(aac_dec, enc_ptr, data_len, s->dec_buf, &aac_info);
|
||||
}
|
||||
if((dec_samples <= 0) || (data_len <= 0)) {
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
goto aac_decode_frame_end;
|
||||
}
|
||||
send_data = (int16_t*)send_frame_buf->data;
|
||||
if(aac_info.channels == 2) {
|
||||
for(uint32_t i=0; i<dec_samples; i++)
|
||||
send_data[i] = s->dec_buf[2*i];
|
||||
}
|
||||
else {
|
||||
for(uint32_t i=0; i<dec_samples; i++)
|
||||
send_data[i] = s->dec_buf[i];
|
||||
}
|
||||
send_frame_buf->len = dec_samples*2;
|
||||
send_frame_buf->mtype = F_AUDIO;
|
||||
send_frame_buf->stype = FSTYPE_AUDIO_PCM;
|
||||
s->audio_track.samplerate = aac_info.samplerate;
|
||||
if(s->use_tpc && !s->autpc_msi) {
|
||||
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
|
||||
if(s->autpc_msi == NULL) {
|
||||
goto aac_decode_end;
|
||||
}
|
||||
if(s->direct_to_dac) {
|
||||
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_add_output(s->msi, NULL, s->autpc_msi->name);
|
||||
}
|
||||
ret = msi_output_fb(s->msi, send_frame_buf);
|
||||
AAC_DEBUG("aac decode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
aac_decode_frame_end:
|
||||
AAC_DEBUG("aac decode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
|
||||
msi_delete_fb(s->msi, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
}
|
||||
else {
|
||||
if(clear_finish == 0) {
|
||||
clear_finish = 1;
|
||||
os_event_set(&s->event, coder_clear_finish_event, NULL);
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
goto aac_decode_end;
|
||||
}
|
||||
}
|
||||
aac_decode_end:
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
if(recv_frame_buf) {
|
||||
msi_delete_fb(NULL, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
}
|
||||
if(send_frame_buf) {
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
if(aac_dec)
|
||||
audio_coder_close(aac_dec);
|
||||
}
|
||||
static void aac_decode_thread(void *d)
|
||||
{
|
||||
struct aac_decode_struct *s = (struct aac_decode_struct *)d;
|
||||
|
||||
msi_get(s->msi);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
s->msi->enable = 1;
|
||||
if(s->aac_fp) {
|
||||
do {
|
||||
osal_fseek(s->aac_fp, 0);
|
||||
aac_file_decode(s);
|
||||
if(s->current_status == AUCODEC_EXIT) {
|
||||
break;
|
||||
}
|
||||
}while(s->loop_mode);
|
||||
}
|
||||
else
|
||||
aac_msi_decode(s);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
os_event_set(&s->event, coder_exit_event, NULL);
|
||||
|
||||
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
|
||||
s->current_status = AUCODEC_END;
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
|
||||
if(s->src_msi) {
|
||||
msi_del_output(s->src_msi, NULL, s->msi->name);
|
||||
s->src_msi = NULL;
|
||||
}
|
||||
|
||||
if(s->next_status != AUCODEC_EXIT)
|
||||
msi_destroy(s->msi);
|
||||
|
||||
msi_put(s->msi);
|
||||
}
|
||||
|
||||
static int32_t aac_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct aac_decode_struct *aac_decode_s = (struct aac_decode_struct*)(msi->priv);
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_AUCODER:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(aac_decode_s) {
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUCODER_PAUSE:
|
||||
{
|
||||
if(aac_decode_s->current_status == AUCODEC_RUN) {
|
||||
aac_decode_s->next_status = AUCODEC_PAUSE;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CONTINUE:
|
||||
{
|
||||
if(aac_decode_s->current_status == AUCODEC_PAUSE) {
|
||||
aac_decode_s->next_status = AUCODEC_RUN;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_STATUS:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(aac_decode_s->current_status);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SPEED:
|
||||
{
|
||||
aac_decode_s->speed = (uint8_t)param2;
|
||||
ret = msi_output_cmd(aac_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(aac_decode_s->speed));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_SPEED:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(aac_decode_s->speed);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_PITCH:
|
||||
{
|
||||
aac_decode_s->pitch = (uint8_t)param2;
|
||||
ret = msi_output_cmd(aac_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(aac_decode_s->pitch));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_PITCH:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(aac_decode_s->pitch);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CLEAR_STREAM:
|
||||
{
|
||||
os_event_set(&aac_decode_s->event, coder_clear_event, NULL);
|
||||
os_event_wait(&aac_decode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
msi_output_cmd(aac_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(aac_decode_s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_CLEAR_STREAM,(uint32_t)(&(aac_decode_s->audio_track)));
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SRCMSI:
|
||||
{
|
||||
if(aac_decode_s->src_msi) {
|
||||
msi_del_output(aac_decode_s->src_msi, NULL, msi->name);
|
||||
}
|
||||
aac_decode_s->src_msi = NULL;
|
||||
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
|
||||
if(ret == RET_OK) {
|
||||
aac_decode_s->src_msi = (struct msi*)param2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DIRECT_TO_DAC:
|
||||
{
|
||||
uint32_t direct_to_dac = param2;
|
||||
if(direct_to_dac && aac_decode_s->direct_to_dac == 0) {
|
||||
aac_decode_s->direct_to_dac = 1;
|
||||
if(aac_decode_s->use_tpc == 0) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(aac_decode_s->autpc_msi) {
|
||||
msi_add_output(aac_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(aac_decode_s->audio_track)));
|
||||
}
|
||||
else if(aac_decode_s->direct_to_dac == 1) {
|
||||
aac_decode_s->direct_to_dac = 0;
|
||||
if(aac_decode_s->use_tpc == 0) {
|
||||
msi_del_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(aac_decode_s->autpc_msi) {
|
||||
msi_del_output(aac_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
aac_decode_s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(aac_decode_s->audio_track)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DEINIT:
|
||||
{
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->mtype == F_AUDIO) {
|
||||
ret = RET_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(aac_decode_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
fbpool_put(&aac_decode_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if(aac_decode_s && aac_decode_s->task_hdl) {
|
||||
aac_decode_s->next_status = AUCODEC_EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(aac_decode_s) {
|
||||
if(aac_decode_s->task_hdl) {
|
||||
os_event_wait(&aac_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
}
|
||||
for(uint32_t i=0; i<MAX_AAC_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (aac_decode_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
AAC_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&aac_decode_s->tx_pool);
|
||||
if(aac_decode_s->event.hdl) {
|
||||
os_event_del(&aac_decode_s->event);
|
||||
}
|
||||
if(aac_decode_s->aac_fp) {
|
||||
osal_fclose(aac_decode_s->aac_fp);
|
||||
aac_decode_s->aac_fp = NULL;
|
||||
}
|
||||
if(aac_decode_s->autpc_msi) {
|
||||
autpc_msi_deinit(aac_decode_s->autpc_msi);
|
||||
aac_decode_s->autpc_msi = NULL;
|
||||
}
|
||||
if(aac_decode_s->msi_name) {
|
||||
AAC_CODE_FREE(aac_decode_s->msi_name);
|
||||
aac_decode_s->msi_name = NULL;
|
||||
}
|
||||
AAC_CODE_FREE(aac_decode_s);
|
||||
aac_decode_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *aac_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init)
|
||||
{
|
||||
#if AUDIO_EN
|
||||
char *msi_name = NULL;
|
||||
|
||||
msi_name = (char*)AAC_CODE_ZALLOC(sizeof(char)*32);
|
||||
if(msi_name == NULL) {
|
||||
os_printf("alloc autpc msi namefail\n");
|
||||
return NULL;
|
||||
}
|
||||
os_snprintf(msi_name, 20, "SR_AAC_DECODE_""%04d", (int)(os_jiffies()));
|
||||
struct msi *msi = msi_new(msi_name, MAX_AAC_DECODE_RXBUF, NULL);
|
||||
if(msi == NULL) {
|
||||
AAC_INFO("create aac decode msi fail!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
struct aac_decode_struct *aac_decode_s = (struct aac_decode_struct*)AAC_CODE_ZALLOC(sizeof(struct aac_decode_struct));
|
||||
if(!aac_decode_s) {
|
||||
AAC_INFO("aac_decode_s malloc fail!\r\n");
|
||||
goto aac_decode_init_err;
|
||||
}
|
||||
msi->priv = aac_decode_s;
|
||||
msi->action = (msi_action)aac_decode_msi_action;
|
||||
fbpool_init(&aac_decode_s->tx_pool, MAX_AAC_DECODE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_AAC_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (aac_decode_s->tx_pool.pool)+i;
|
||||
frame_buf->data = (uint8_t*)AAC_CODE_MALLOC(1024 * sizeof(int16_t));
|
||||
if(frame_buf->data == NULL)
|
||||
{
|
||||
AAC_INFO("aac decode malloc framebuff data fail!\r\n");
|
||||
goto aac_decode_init_err;
|
||||
}
|
||||
frame_buf->priv = &(aac_decode_s->audio_track);
|
||||
}
|
||||
if(os_event_init(&aac_decode_s->event) != RET_OK) {
|
||||
AAC_INFO("create aac decode event fail!\r\n");
|
||||
goto aac_decode_init_err;
|
||||
}
|
||||
if(filename) {
|
||||
aac_decode_s->aac_fp = osal_fopen((const char*)filename, "rb");
|
||||
if(aac_decode_s->aac_fp == NULL) {
|
||||
AAC_INFO("open aac file %s fail!\r\n", filename);
|
||||
goto aac_decode_init_err;
|
||||
}
|
||||
}
|
||||
if(audec_init->src_msi && (msi_add_output(audec_init->src_msi, NULL, msi->name) != RET_OK)) {
|
||||
goto aac_decode_init_err;
|
||||
}
|
||||
aac_decode_s->msi = msi;
|
||||
aac_decode_s->msi_name = msi_name;
|
||||
aac_decode_s->src_msi = audec_init->src_msi;
|
||||
aac_decode_s->loop_mode = loop_mode;
|
||||
aac_decode_s->direct_to_dac = audec_init->direct_to_dac;
|
||||
aac_decode_s->use_tpc = audec_init->use_tpc;
|
||||
aac_decode_s->speed = audec_init->speed;
|
||||
aac_decode_s->pitch = audec_init->pitch;
|
||||
aac_decode_s->destroy_self = audec_init->destroy_self;
|
||||
aac_decode_s->audio_track.priority = audec_init->priority;
|
||||
aac_decode_s->audio_track.track_type = audec_init->track_type;
|
||||
aac_decode_s->next_status = AUCODEC_RUN;
|
||||
aac_decode_s->current_status = AUCODEC_RUN;
|
||||
if(audec_init->direct_to_dac && !aac_decode_s->use_tpc) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
#if AAC_DEC_CTRL == AUCODER_RUN_IN_CPU1
|
||||
aac_decode_s->task_hdl = os_task_create("aac_decode_thread", aac_decode_thread, (void*)aac_decode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
#else
|
||||
aac_decode_s->task_hdl = os_task_create("aac_decode_thread", aac_decode_thread, (void*)aac_decode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 2048);
|
||||
#endif
|
||||
if(aac_decode_s->task_hdl == NULL) {
|
||||
AAC_INFO("create aac decode task fail!\r\n");
|
||||
goto aac_decode_init_err;
|
||||
}
|
||||
return msi;
|
||||
|
||||
aac_decode_init_err:
|
||||
msi_destroy(msi);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
404
sdk/app/audio_media_ctrl/aac/aac_encode.c
Normal file
404
sdk/app/audio_media_ctrl/aac/aac_encode.c
Normal file
@@ -0,0 +1,404 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/audio/audio_code/audio_code.h"
|
||||
#include "osal_file.h"
|
||||
#include "aac_code.h"
|
||||
|
||||
#define MAX_AAC_ENCODE_RXBUF 4
|
||||
#define MAX_AAC_ENCODE_TXBUF 20
|
||||
|
||||
struct aac_encode_struct {
|
||||
struct fbpool tx_pool;
|
||||
struct os_event event;
|
||||
struct msi *msi;
|
||||
struct msi *src_msi;
|
||||
void *task_hdl;
|
||||
void *aac_fp;
|
||||
uint8_t direct_to_record;
|
||||
uint8_t stop_record;
|
||||
uint8_t destroy_self;
|
||||
uint8_t next_status;
|
||||
uint8_t current_status;
|
||||
uint8_t enc_buf[1536];
|
||||
int16_t inbuf[1024];
|
||||
uint32_t samplerate;
|
||||
AUDIO_INFO audio_info;
|
||||
};
|
||||
|
||||
static void aac_encode_thread(void *d)
|
||||
{
|
||||
uint8_t clear_finish = 1;
|
||||
uint8_t get_audio_time = 0;
|
||||
uint8_t update_audio_time = 0;
|
||||
uint8_t *send_data = NULL;
|
||||
int16_t *recv_data = NULL;
|
||||
int32_t enc_bytes = 0;
|
||||
int32_t ret = 0;
|
||||
uint32_t data_len = 0;
|
||||
uint32_t data_offset = 0;
|
||||
uint32_t inbuf_offset = 0;
|
||||
uint32_t inbuf_reslen = 2048;
|
||||
uint32_t audio_time = 0;
|
||||
uint32_t clear_flag = 0;
|
||||
struct framebuff *send_frame_buf = NULL;
|
||||
struct framebuff *recv_frame_buf = NULL;
|
||||
struct aac_encode_struct *s = (struct aac_encode_struct *)d;
|
||||
AUCODE_HDL *aac_enc = NULL;
|
||||
|
||||
s->msi->enable = 1;
|
||||
msi_get(s->msi);
|
||||
|
||||
aac_enc = audio_coder_open(AAC_ENC, s->samplerate, 1);
|
||||
if (aac_enc == NULL)
|
||||
goto aac_encode_thread_end;
|
||||
|
||||
s->audio_info.nsamples = 1024;
|
||||
s->audio_info.time_interval = s->audio_info.nsamples * 1000 / s->samplerate;
|
||||
s->audio_info.samplerate = s->samplerate;
|
||||
|
||||
while(1) {
|
||||
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
|
||||
if(clear_flag & coder_clear_event) {
|
||||
clear_flag = 0;
|
||||
clear_finish = 0;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
audio_coder_close(aac_enc);
|
||||
aac_enc = audio_coder_open(AAC_ENC, s->samplerate, 1);
|
||||
if (aac_enc == NULL)
|
||||
goto aac_encode_thread_end;
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
inbuf_reslen = 2048;
|
||||
inbuf_offset = 0;
|
||||
}
|
||||
recv_frame_buf = msi_get_fb(s->msi, 0);
|
||||
if(recv_frame_buf) {
|
||||
if(clear_finish == 0) {
|
||||
inbuf_reslen = 2048;
|
||||
inbuf_offset = 0;
|
||||
goto aac_encode_frame_end;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
goto aac_encode_frame_end;
|
||||
}
|
||||
else {
|
||||
s->current_status = AUCODEC_RUN;
|
||||
recv_data = (int16_t*)recv_frame_buf->data;
|
||||
data_len = recv_frame_buf->len;
|
||||
data_offset = 0;
|
||||
if(!get_audio_time) {
|
||||
get_audio_time = 1;
|
||||
audio_time = recv_frame_buf->time;
|
||||
}
|
||||
if(update_audio_time) {
|
||||
audio_time = recv_frame_buf->time;
|
||||
update_audio_time = 0;
|
||||
}
|
||||
while(data_len >= inbuf_reslen) {
|
||||
os_memcpy(s->inbuf + (inbuf_offset/2), recv_data + (data_offset/2), inbuf_reslen);
|
||||
data_len -= inbuf_reslen;
|
||||
data_offset += inbuf_reslen;
|
||||
enc_bytes = audio_encode_data(aac_enc, s->inbuf, 1024, s->enc_buf);
|
||||
inbuf_reslen = 2048;
|
||||
inbuf_offset = 0;
|
||||
if(enc_bytes < 0) {
|
||||
AAC_INFO("aac encode failed\n");
|
||||
break;
|
||||
}
|
||||
if(enc_bytes > 0) {
|
||||
if(s->aac_fp)
|
||||
osal_fwrite(s->enc_buf, 1, enc_bytes, s->aac_fp);
|
||||
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(send_frame_buf) {
|
||||
send_frame_buf->data = (uint8_t*)AAC_CODE_MALLOC(enc_bytes);
|
||||
if(!send_frame_buf->data) {
|
||||
AAC_INFO("aac encode malloc send_frame_buf->data fail!\n");
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
goto aac_encode_frame_end;
|
||||
}
|
||||
send_data = send_frame_buf->data;
|
||||
os_memcpy(send_data, s->enc_buf, enc_bytes);
|
||||
send_frame_buf->len = enc_bytes;
|
||||
send_frame_buf->mtype = F_AUDIO;
|
||||
send_frame_buf->time = audio_time;
|
||||
send_frame_buf->priv = &(s->audio_info);
|
||||
ret = msi_output_fb(s->msi, send_frame_buf);
|
||||
AAC_DEBUG("aac encode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
audio_time += (1024 * 1000 / s->samplerate);
|
||||
if(data_len == 0)
|
||||
update_audio_time = 1;
|
||||
}
|
||||
aac_encode_frame_end:
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
if(data_len) {
|
||||
os_memcpy(s->inbuf + (inbuf_offset/2), recv_data + (data_offset/2), data_len);
|
||||
inbuf_reslen -= data_len;
|
||||
inbuf_offset += data_len;
|
||||
data_offset = 0;
|
||||
data_len = 0;
|
||||
}
|
||||
}
|
||||
AAC_DEBUG("aac encode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
|
||||
msi_delete_fb(s->msi, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
}
|
||||
else {
|
||||
if(clear_finish == 0) {
|
||||
clear_finish = 1;
|
||||
os_event_set(&s->event, coder_clear_finish_event, NULL);
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
if(s->stop_record) {
|
||||
if(s->aac_fp) {
|
||||
osal_fclose(s->aac_fp);
|
||||
s->aac_fp = NULL;
|
||||
}
|
||||
s->direct_to_record = 0;
|
||||
s->stop_record = 0;
|
||||
}
|
||||
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
goto aac_encode_thread_end;
|
||||
}
|
||||
}
|
||||
aac_encode_thread_end:
|
||||
if(aac_enc)
|
||||
audio_coder_close(aac_enc);
|
||||
os_event_set(&s->event, coder_exit_event, NULL);
|
||||
|
||||
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
|
||||
s->current_status = AUCODEC_END;
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
|
||||
if(s->src_msi) {
|
||||
msi_del_output(s->src_msi, NULL, s->msi->name);
|
||||
s->src_msi = NULL;
|
||||
}
|
||||
|
||||
if(s->next_status != AUCODEC_EXIT) {
|
||||
msi_destroy(s->msi);
|
||||
}
|
||||
|
||||
msi_put(s->msi);
|
||||
}
|
||||
|
||||
static int32_t aac_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct aac_encode_struct *aac_encode_s = (struct aac_encode_struct*)(msi->priv);
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_AUCODER:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(aac_encode_s) {
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUCODER_PAUSE:
|
||||
{
|
||||
if(aac_encode_s->current_status == AUCODEC_RUN) {
|
||||
aac_encode_s->next_status = AUCODEC_PAUSE;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CONTINUE:
|
||||
{
|
||||
if(aac_encode_s->current_status == AUCODEC_PAUSE) {
|
||||
aac_encode_s->next_status = AUCODEC_RUN;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_STATUS:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(aac_encode_s->current_status);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CLEAR_STREAM:
|
||||
{
|
||||
os_event_set(&aac_encode_s->event, coder_clear_event, NULL);
|
||||
os_event_wait(&aac_encode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SRCMSI:
|
||||
{
|
||||
if(aac_encode_s->src_msi) {
|
||||
msi_del_output(aac_encode_s->src_msi, NULL, msi->name);
|
||||
}
|
||||
aac_encode_s->src_msi = NULL;
|
||||
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
|
||||
if(ret == RET_OK) {
|
||||
aac_encode_s->src_msi = (struct msi*)param2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DEINIT:
|
||||
{
|
||||
aac_encode_s->stop_record = param2;
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->mtype == F_AUDIO) {
|
||||
ret = RET_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(aac_encode_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->data) {
|
||||
AAC_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
fbpool_put(&aac_encode_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if(aac_encode_s && aac_encode_s->task_hdl) {
|
||||
aac_encode_s->next_status = AUCODEC_EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(aac_encode_s) {
|
||||
if(aac_encode_s->task_hdl) {
|
||||
os_event_wait(&aac_encode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
}
|
||||
for(uint32_t i=0; i<MAX_AAC_ENCODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (aac_encode_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
AAC_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&aac_encode_s->tx_pool);
|
||||
if(aac_encode_s->event.hdl) {
|
||||
os_event_del(&aac_encode_s->event);
|
||||
}
|
||||
if(aac_encode_s->aac_fp) {
|
||||
osal_fclose(aac_encode_s->aac_fp);
|
||||
aac_encode_s->aac_fp = NULL;
|
||||
}
|
||||
AAC_CODE_FREE(aac_encode_s);
|
||||
aac_encode_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *aac_encode_init(char *filename, uint32_t samplerate, uint8_t direct_to_record, AUENC_INIT *auenc_init)
|
||||
{
|
||||
#if AUDIO_EN
|
||||
uint8_t msi_isnew = 0;
|
||||
struct aac_encode_struct *aac_encode_s = NULL;
|
||||
|
||||
struct msi *msi = msi_new("SR_AAC_ENCODE", MAX_AAC_ENCODE_RXBUF, &msi_isnew);
|
||||
if(msi && !msi_isnew) {
|
||||
aac_encode_s = (struct aac_encode_struct*)(msi->priv);
|
||||
if(aac_encode_s) {
|
||||
if((samplerate != aac_encode_s->samplerate) || (direct_to_record && aac_encode_s->direct_to_record)) {
|
||||
AAC_INFO("aac_encode_init conflict!\r\n");
|
||||
goto aac_encode_init_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(msi && msi_isnew) {
|
||||
aac_encode_s = (struct aac_encode_struct *)AAC_CODE_ZALLOC(sizeof(struct aac_encode_struct));
|
||||
if(!aac_encode_s) {
|
||||
AAC_INFO("aac_encode_s malloc fail!\r\n");
|
||||
goto aac_encode_init_err;
|
||||
}
|
||||
msi->priv = aac_encode_s;
|
||||
msi->action = (msi_action)aac_encode_msi_action;
|
||||
fbpool_init(&aac_encode_s->tx_pool, MAX_AAC_ENCODE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_AAC_ENCODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (aac_encode_s->tx_pool.pool)+i;
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
if(os_event_init(&aac_encode_s->event) != RET_OK) {
|
||||
AAC_INFO("create aac encode event fail!\r\n");
|
||||
goto aac_encode_init_err;
|
||||
}
|
||||
if(auenc_init->src_msi && (msi_add_output(auenc_init->src_msi, NULL, msi->name) != RET_OK)) {
|
||||
goto aac_encode_init_err;
|
||||
}
|
||||
aac_encode_s->msi = msi;
|
||||
aac_encode_s->src_msi = auenc_init->src_msi;
|
||||
aac_encode_s->samplerate = samplerate;
|
||||
aac_encode_s->destroy_self = auenc_init->destroy_self;
|
||||
aac_encode_s->next_status = AUCODEC_RUN;
|
||||
aac_encode_s->current_status = AUCODEC_RUN;
|
||||
}
|
||||
else {
|
||||
AAC_INFO("create aac encode msi fail!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
if(direct_to_record && filename) {
|
||||
aac_encode_s->aac_fp = osal_fopen((const char*)filename, "wb+");
|
||||
if(aac_encode_s->aac_fp == NULL) {
|
||||
AAC_INFO("open aac record file %s fail!\r\n", filename);
|
||||
goto aac_encode_init_err;
|
||||
}
|
||||
aac_encode_s->direct_to_record = 1;
|
||||
}
|
||||
else if(direct_to_record && !filename) {
|
||||
AAC_INFO("aac record file is null!\r\n");
|
||||
goto aac_encode_init_err;
|
||||
}
|
||||
else if(!direct_to_record && filename) {
|
||||
AAC_INFO("aac record direct_to_record is 0!\r\n");
|
||||
goto aac_encode_init_err;
|
||||
}
|
||||
|
||||
if(msi_isnew) {
|
||||
#if AAC_ENC_CTRL == AUCODER_RUN_IN_CPU1
|
||||
aac_encode_s->task_hdl = os_task_create("aac_encode_thread", aac_encode_thread, (void*)aac_encode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
#else
|
||||
aac_encode_s->task_hdl = os_task_create("aac_encode_thread", aac_encode_thread, (void*)aac_encode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 3072);
|
||||
#endif
|
||||
if(aac_encode_s->task_hdl == NULL) {
|
||||
AAC_INFO("create aac encode task fail!\r\n");
|
||||
goto aac_encode_init_err;
|
||||
}
|
||||
}
|
||||
return msi;
|
||||
|
||||
aac_encode_init_err:
|
||||
msi_destroy(msi);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
27
sdk/app/audio_media_ctrl/alaw/alaw_code.h
Normal file
27
sdk/app/audio_media_ctrl/alaw/alaw_code.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef _ALAW_CODE_H_
|
||||
#define _ALAW_CODE_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "audio_code_ctrl.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define ALAW_CODE_MALLOC av_psram_malloc
|
||||
#define ALAW_CODE_ZALLOC av_psram_zalloc
|
||||
#define ALAW_CODE_CALLOC av_psram_calloc
|
||||
#define ALAW_CODE_FREE av_psram_free
|
||||
#else
|
||||
#define ALAW_CODE_MALLOC av_malloc
|
||||
#define ALAW_CODE_ZALLOC av_zalloc
|
||||
#define ALAW_CODE_CALLOC av_calloc
|
||||
#define ALAW_CODE_FREE av_free
|
||||
#endif
|
||||
|
||||
#define ALAW_DEBUG(fmt, args...) //os_printf(fmt, ##args)
|
||||
#define ALAW_INFO os_printf
|
||||
|
||||
struct msi *alaw_encode_init(uint32_t samplerate, AUENC_INIT *auenc_init);
|
||||
struct msi *alaw_decode_init(AUDEC_INIT *audec_init);
|
||||
|
||||
#endif
|
||||
427
sdk/app/audio_media_ctrl/alaw/alaw_decode.c
Normal file
427
sdk/app/audio_media_ctrl/alaw/alaw_decode.c
Normal file
@@ -0,0 +1,427 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/audio/audio_code/audio_code.h"
|
||||
#include "autpc_msi/autpc_msi.h"
|
||||
#include "alaw_code.h"
|
||||
|
||||
#define MAX_ALAW_DECODE_RXBUF 4
|
||||
#define MAX_ALAW_DECODE_TXBUF 4
|
||||
|
||||
struct alaw_decode_struct {
|
||||
AUDIO_TRACK audio_track;
|
||||
struct fbpool tx_pool;
|
||||
struct os_event event;
|
||||
struct msi *msi;
|
||||
struct msi *src_msi;
|
||||
struct msi *autpc_msi;
|
||||
char *msi_name;
|
||||
void *task_hdl;
|
||||
uint8_t direct_to_dac;
|
||||
uint8_t use_tpc;
|
||||
uint8_t speed;
|
||||
uint8_t pitch;
|
||||
uint8_t destroy_self;
|
||||
uint8_t next_status;
|
||||
uint8_t current_status;
|
||||
int16_t dec_buf[960]; //按照16k、60ms的最大长度,若超过该长度则需修改数组大小;
|
||||
};
|
||||
|
||||
static void alaw_decode(struct alaw_decode_struct *s)
|
||||
{
|
||||
uint8_t clear_finish = 1;
|
||||
uint8_t *enc_ptr = NULL;
|
||||
int32_t ret = 0;
|
||||
int32_t data_len = 0;
|
||||
int32_t dec_samples = 0;
|
||||
uint32_t clear_flag = 0;
|
||||
struct framebuff *recv_frame_buf = NULL;
|
||||
struct framebuff *send_frame_buf = NULL;
|
||||
AUCODE_HDL *alaw_dec = NULL;
|
||||
AUCODE_FRAME_INFO alaw_info;
|
||||
|
||||
alaw_dec = audio_coder_open(ALAW_DEC, 8000, 1);
|
||||
if(!alaw_dec)
|
||||
return;
|
||||
while(1) {
|
||||
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
|
||||
if(clear_flag & coder_clear_event) {
|
||||
clear_flag = 0;
|
||||
clear_finish = 0;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
audio_coder_close(alaw_dec);
|
||||
alaw_dec = audio_coder_open(ALAW_DEC, 8000, 1);
|
||||
if(!alaw_dec)
|
||||
return;
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
}
|
||||
recv_frame_buf = msi_get_fb(s->msi, 0);
|
||||
if(recv_frame_buf) {
|
||||
if(clear_finish == 0) {
|
||||
goto alaw_decode_frame_end;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
goto alaw_decode_frame_end;
|
||||
}
|
||||
else {
|
||||
s->current_status = AUCODEC_RUN;
|
||||
while(!send_frame_buf) {
|
||||
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(!send_frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
data_len = recv_frame_buf->len;
|
||||
if(data_len > 0) {
|
||||
enc_ptr = recv_frame_buf->data;
|
||||
dec_samples = audio_decode_data(alaw_dec, enc_ptr, data_len, s->dec_buf, &alaw_info);
|
||||
}
|
||||
if((dec_samples <= 0) || (data_len <= 0)) {
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
goto alaw_decode_frame_end;
|
||||
}
|
||||
send_frame_buf->data = (uint8_t*)ALAW_CODE_MALLOC(dec_samples*2);
|
||||
if(!send_frame_buf->data) {
|
||||
ALAW_INFO("alaw decode malloc send_frame_buf->data fail!\n");
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
goto alaw_decode_frame_end;
|
||||
}
|
||||
os_memcpy(send_frame_buf->data, s->dec_buf, dec_samples*2);
|
||||
send_frame_buf->len = dec_samples*2;
|
||||
send_frame_buf->mtype = F_AUDIO;
|
||||
send_frame_buf->stype = FSTYPE_AUDIO_PCM;
|
||||
s->audio_track.samplerate = alaw_info.samplerate;
|
||||
if(s->use_tpc && !s->autpc_msi) {
|
||||
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
|
||||
if(s->autpc_msi == NULL) {
|
||||
goto alaw_decode_end;
|
||||
}
|
||||
if(s->direct_to_dac) {
|
||||
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_add_output(s->msi, NULL, s->autpc_msi->name);
|
||||
}
|
||||
ret = msi_output_fb(s->msi, send_frame_buf);
|
||||
ALAW_DEBUG("alaw decode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
alaw_decode_frame_end:
|
||||
ALAW_DEBUG("alaw decode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
|
||||
msi_delete_fb(s->msi, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
}
|
||||
else {
|
||||
if(clear_finish == 0) {
|
||||
clear_finish = 1;
|
||||
os_event_set(&s->event, coder_clear_finish_event, NULL);
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
goto alaw_decode_end;
|
||||
}
|
||||
}
|
||||
alaw_decode_end:
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
if(recv_frame_buf) {
|
||||
msi_delete_fb(NULL, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
}
|
||||
if(send_frame_buf) {
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
if(alaw_dec)
|
||||
audio_coder_close(alaw_dec);
|
||||
}
|
||||
|
||||
static void alaw_decode_thread(void *d)
|
||||
{
|
||||
struct alaw_decode_struct *s = (struct alaw_decode_struct *)d;
|
||||
|
||||
msi_get(s->msi);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
s->msi->enable = 1;
|
||||
alaw_decode(s);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
os_event_set(&s->event, coder_exit_event, NULL);
|
||||
|
||||
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
|
||||
s->current_status = AUCODEC_END;
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
|
||||
if(s->src_msi) {
|
||||
msi_del_output(s->src_msi, NULL, s->msi->name);
|
||||
s->src_msi = NULL;
|
||||
}
|
||||
|
||||
if(s->next_status != AUCODEC_EXIT)
|
||||
msi_destroy(s->msi);
|
||||
|
||||
msi_put(s->msi);
|
||||
}
|
||||
|
||||
static int32_t alaw_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct alaw_decode_struct *alaw_decode_s = (struct alaw_decode_struct*)(msi->priv);
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_AUCODER:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(alaw_decode_s) {
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUCODER_PAUSE:
|
||||
{
|
||||
if(alaw_decode_s->current_status == AUCODEC_RUN) {
|
||||
alaw_decode_s->next_status = AUCODEC_PAUSE;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CONTINUE:
|
||||
{
|
||||
if(alaw_decode_s->current_status == AUCODEC_PAUSE) {
|
||||
alaw_decode_s->next_status = AUCODEC_RUN;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_STATUS:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(alaw_decode_s->current_status);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SPEED:
|
||||
{
|
||||
alaw_decode_s->speed = (uint8_t)param2;
|
||||
ret = msi_output_cmd(alaw_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(alaw_decode_s->speed));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_SPEED:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(alaw_decode_s->speed);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_PITCH:
|
||||
{
|
||||
alaw_decode_s->pitch = (uint8_t)param2;
|
||||
ret = msi_output_cmd(alaw_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(alaw_decode_s->pitch));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_PITCH:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(alaw_decode_s->pitch);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CLEAR_STREAM:
|
||||
{
|
||||
os_event_set(&alaw_decode_s->event, coder_clear_event, NULL);
|
||||
os_event_wait(&alaw_decode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
msi_output_cmd(alaw_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(alaw_decode_s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_CLEAR_STREAM,(uint32_t)(&(alaw_decode_s->audio_track)));
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SRCMSI:
|
||||
{
|
||||
if(alaw_decode_s->src_msi) {
|
||||
msi_del_output(alaw_decode_s->src_msi, NULL, msi->name);
|
||||
}
|
||||
alaw_decode_s->src_msi = NULL;
|
||||
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
|
||||
if(ret == RET_OK) {
|
||||
alaw_decode_s->src_msi = (struct msi*)param2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DIRECT_TO_DAC:
|
||||
{
|
||||
uint32_t direct_to_dac = param2;
|
||||
if(direct_to_dac && alaw_decode_s->direct_to_dac == 0) {
|
||||
alaw_decode_s->direct_to_dac = 1;
|
||||
if(alaw_decode_s->use_tpc == 0) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(alaw_decode_s->autpc_msi) {
|
||||
msi_add_output(alaw_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(alaw_decode_s->audio_track)));
|
||||
}
|
||||
else if(alaw_decode_s->direct_to_dac == 1) {
|
||||
alaw_decode_s->direct_to_dac = 0;
|
||||
if(alaw_decode_s->use_tpc == 0) {
|
||||
msi_del_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(alaw_decode_s->autpc_msi) {
|
||||
msi_del_output(alaw_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
alaw_decode_s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(alaw_decode_s->audio_track)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DEINIT:
|
||||
{
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->mtype == F_AUDIO) {
|
||||
ret = RET_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(alaw_decode_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->data) {
|
||||
ALAW_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
fbpool_put(&alaw_decode_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if(alaw_decode_s && alaw_decode_s->task_hdl) {
|
||||
alaw_decode_s->next_status = AUCODEC_EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(alaw_decode_s) {
|
||||
if(alaw_decode_s->task_hdl) {
|
||||
os_event_wait(&alaw_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
}
|
||||
for(uint32_t i=0; i<MAX_ALAW_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (alaw_decode_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
ALAW_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&alaw_decode_s->tx_pool);
|
||||
if(alaw_decode_s->event.hdl) {
|
||||
os_event_del(&alaw_decode_s->event);
|
||||
}
|
||||
if(alaw_decode_s->autpc_msi) {
|
||||
autpc_msi_deinit(alaw_decode_s->autpc_msi);
|
||||
alaw_decode_s->autpc_msi = NULL;
|
||||
}
|
||||
if(alaw_decode_s->msi_name) {
|
||||
ALAW_CODE_FREE(alaw_decode_s->msi_name);
|
||||
alaw_decode_s->msi_name = NULL;
|
||||
}
|
||||
ALAW_CODE_FREE(alaw_decode_s);
|
||||
alaw_decode_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *alaw_decode_init(AUDEC_INIT *audec_init)
|
||||
{
|
||||
#if AUDIO_EN
|
||||
char *msi_name = NULL;
|
||||
|
||||
msi_name = (char*)ALAW_CODE_ZALLOC(sizeof(char)*32);
|
||||
if(msi_name == NULL) {
|
||||
os_printf("alloc autpc msi namefail\n");
|
||||
return NULL;
|
||||
}
|
||||
os_snprintf(msi_name, 20, "SR_ALAW_DECODE_""%04d", (int)(os_jiffies()));
|
||||
struct msi *msi = msi_new(msi_name, MAX_ALAW_DECODE_RXBUF, NULL);
|
||||
if(msi == NULL) {
|
||||
ALAW_INFO("create alaw decode msi fail!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
struct alaw_decode_struct *alaw_decode_s = (struct alaw_decode_struct*)ALAW_CODE_ZALLOC(sizeof(struct alaw_decode_struct));
|
||||
if(!alaw_decode_s) {
|
||||
ALAW_INFO("alaw_decode_s malloc fail!\r\n");
|
||||
goto alaw_decode_init_err;
|
||||
}
|
||||
msi->priv = alaw_decode_s;
|
||||
msi->action = (msi_action)alaw_decode_msi_action;
|
||||
fbpool_init(&alaw_decode_s->tx_pool, MAX_ALAW_DECODE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_ALAW_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (alaw_decode_s->tx_pool.pool)+i;
|
||||
frame_buf->data = NULL;
|
||||
frame_buf->priv = &(alaw_decode_s->audio_track);
|
||||
}
|
||||
if(os_event_init(&alaw_decode_s->event) != RET_OK) {
|
||||
ALAW_INFO("create alaw decode event fail!\r\n");
|
||||
goto alaw_decode_init_err;
|
||||
}
|
||||
if(audec_init->src_msi && (msi_add_output(audec_init->src_msi, NULL, msi->name) != RET_OK)) {
|
||||
goto alaw_decode_init_err;
|
||||
}
|
||||
alaw_decode_s->msi = msi;
|
||||
alaw_decode_s->msi_name = msi_name;
|
||||
alaw_decode_s->src_msi = audec_init->src_msi;
|
||||
alaw_decode_s->direct_to_dac = audec_init->direct_to_dac;
|
||||
alaw_decode_s->use_tpc = audec_init->use_tpc;
|
||||
alaw_decode_s->speed = audec_init->speed;
|
||||
alaw_decode_s->pitch = audec_init->pitch;
|
||||
alaw_decode_s->destroy_self = audec_init->destroy_self;
|
||||
alaw_decode_s->audio_track.priority = audec_init->priority;
|
||||
alaw_decode_s->audio_track.track_type = audec_init->track_type;
|
||||
alaw_decode_s->next_status = AUCODEC_RUN;
|
||||
alaw_decode_s->current_status = AUCODEC_RUN;
|
||||
if(audec_init->direct_to_dac && !alaw_decode_s->use_tpc) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
alaw_decode_s->task_hdl = os_task_create("alaw_decode_thread", alaw_decode_thread, (void*)alaw_decode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
if(alaw_decode_s->task_hdl == NULL) {
|
||||
ALAW_INFO("create opus decode task fail!\r\n");
|
||||
goto alaw_decode_init_err;
|
||||
}
|
||||
return msi;
|
||||
|
||||
alaw_decode_init_err:
|
||||
msi_destroy(msi);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
319
sdk/app/audio_media_ctrl/alaw/alaw_encode.c
Normal file
319
sdk/app/audio_media_ctrl/alaw/alaw_encode.c
Normal file
@@ -0,0 +1,319 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/audio/audio_code/audio_code.h"
|
||||
#include "alaw_code.h"
|
||||
|
||||
#define MAX_ALAW_ENCODE_RXBUF 4
|
||||
#define MAX_ALAW_ENCODE_TXBUF 4
|
||||
|
||||
struct alaw_encode_struct {
|
||||
struct fbpool tx_pool;
|
||||
struct os_event event;
|
||||
struct msi *msi;
|
||||
struct msi *src_msi;
|
||||
void *task_hdl;
|
||||
uint8_t destroy_self;
|
||||
uint8_t next_status;
|
||||
uint8_t current_status;
|
||||
uint8_t enc_buf[1024];
|
||||
uint32_t samplerate;
|
||||
AUDIO_INFO audio_info;
|
||||
};
|
||||
|
||||
static void alaw_encode_thread(void *d)
|
||||
{
|
||||
uint8_t clear_finish = 1;
|
||||
uint8_t *send_data = NULL;
|
||||
int16_t *recv_data = NULL;
|
||||
int32_t enc_bytes = 0;
|
||||
int32_t ret = 0;
|
||||
uint32_t data_len = 0;
|
||||
uint32_t clear_flag = 0;
|
||||
struct framebuff *send_frame_buf = NULL;
|
||||
struct framebuff *recv_frame_buf = NULL;
|
||||
struct alaw_encode_struct *s = (struct alaw_encode_struct *)d;
|
||||
AUCODE_HDL *alaw_enc = NULL;
|
||||
|
||||
s->msi->enable = 1;
|
||||
msi_get(s->msi);
|
||||
|
||||
alaw_enc = audio_coder_open(ALAW_ENC, s->samplerate, 1);
|
||||
if (alaw_enc == NULL)
|
||||
goto alaw_encode_thread_end;
|
||||
|
||||
while(1) {
|
||||
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
|
||||
if(clear_flag & coder_clear_event) {
|
||||
clear_flag = 0;
|
||||
clear_finish = 0;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
audio_coder_close(alaw_enc);
|
||||
alaw_enc = audio_coder_open(ALAW_ENC, s->samplerate, 1);
|
||||
if (alaw_enc == NULL)
|
||||
goto alaw_encode_thread_end;
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
}
|
||||
recv_frame_buf = msi_get_fb(s->msi, 0);
|
||||
if(recv_frame_buf) {
|
||||
if(s->audio_info.nsamples == 0) {
|
||||
s->audio_info.nsamples = recv_frame_buf->len / 2;
|
||||
s->audio_info.time_interval = s->audio_info.nsamples * 1000 / s->samplerate;
|
||||
s->audio_info.samplerate = s->samplerate;
|
||||
}
|
||||
if(clear_finish == 0) {
|
||||
goto alaw_encode_frame_end;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
goto alaw_encode_frame_end;
|
||||
}
|
||||
else {
|
||||
s->current_status = AUCODEC_RUN;
|
||||
recv_data = (int16_t*)recv_frame_buf->data;
|
||||
data_len = recv_frame_buf->len;
|
||||
enc_bytes = audio_encode_data(alaw_enc, (int16_t*)recv_data, data_len/2, s->enc_buf);
|
||||
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(send_frame_buf) {
|
||||
send_frame_buf->data = (uint8_t*)ALAW_CODE_MALLOC(enc_bytes);
|
||||
if(!send_frame_buf->data) {
|
||||
ALAW_INFO("alaw encode malloc send_frame_buf->data fail!\n");
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
goto alaw_encode_frame_end;
|
||||
}
|
||||
send_data = send_frame_buf->data;
|
||||
os_memcpy(send_data, s->enc_buf, enc_bytes);
|
||||
send_frame_buf->len = enc_bytes;
|
||||
send_frame_buf->mtype = F_AUDIO;
|
||||
send_frame_buf->time = recv_frame_buf->time;
|
||||
send_frame_buf->priv = &(s->audio_info);
|
||||
ret = msi_output_fb(s->msi, send_frame_buf);
|
||||
ALAW_DEBUG("alaw encode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
}
|
||||
alaw_encode_frame_end:
|
||||
ALAW_DEBUG("alaw encode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
|
||||
msi_delete_fb(s->msi, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
}
|
||||
else {
|
||||
if(clear_finish == 0) {
|
||||
clear_finish = 1;
|
||||
os_event_set(&s->event, coder_clear_finish_event, NULL);
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
goto alaw_encode_thread_end;
|
||||
}
|
||||
}
|
||||
alaw_encode_thread_end:
|
||||
if(alaw_enc)
|
||||
audio_coder_close(alaw_enc);
|
||||
os_event_set(&s->event, coder_exit_event, NULL);
|
||||
|
||||
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
|
||||
s->current_status = AUCODEC_END;
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
|
||||
if(s->src_msi) {
|
||||
msi_del_output(s->src_msi, NULL, s->msi->name);
|
||||
s->src_msi = NULL;
|
||||
}
|
||||
|
||||
if(s->next_status != AUCODEC_EXIT)
|
||||
msi_destroy(s->msi);
|
||||
|
||||
msi_put(s->msi);
|
||||
}
|
||||
|
||||
static int32_t alaw_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct alaw_encode_struct *alaw_encode_s = (struct alaw_encode_struct*)(msi->priv);
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_AUCODER:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(alaw_encode_s) {
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUCODER_PAUSE:
|
||||
{
|
||||
if(alaw_encode_s->current_status == AUCODEC_RUN) {
|
||||
alaw_encode_s->next_status = AUCODEC_PAUSE;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CONTINUE:
|
||||
{
|
||||
if(alaw_encode_s->current_status == AUCODEC_PAUSE) {
|
||||
alaw_encode_s->next_status = AUCODEC_RUN;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_STATUS:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(alaw_encode_s->current_status);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CLEAR_STREAM:
|
||||
{
|
||||
os_event_set(&alaw_encode_s->event, coder_clear_event, NULL);
|
||||
os_event_wait(&alaw_encode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SRCMSI:
|
||||
{
|
||||
if(alaw_encode_s->src_msi) {
|
||||
msi_del_output(alaw_encode_s->src_msi, NULL, msi->name);
|
||||
}
|
||||
alaw_encode_s->src_msi = NULL;
|
||||
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
|
||||
if(ret == RET_OK) {
|
||||
alaw_encode_s->src_msi = (struct msi*)param2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DEINIT:
|
||||
{
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->mtype == F_AUDIO) {
|
||||
ret = RET_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(alaw_encode_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->data) {
|
||||
ALAW_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
fbpool_put(&alaw_encode_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if(alaw_encode_s && alaw_encode_s->task_hdl) {
|
||||
alaw_encode_s->next_status = AUCODEC_EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(alaw_encode_s) {
|
||||
if(alaw_encode_s->task_hdl) {
|
||||
os_event_wait(&alaw_encode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
}
|
||||
for(uint32_t i=0; i<MAX_ALAW_ENCODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (alaw_encode_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
ALAW_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&alaw_encode_s->tx_pool);
|
||||
if(alaw_encode_s->event.hdl) {
|
||||
os_event_del(&alaw_encode_s->event);
|
||||
}
|
||||
ALAW_CODE_FREE(alaw_encode_s);
|
||||
alaw_encode_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *alaw_encode_init(uint32_t samplerate, AUENC_INIT *auenc_init)
|
||||
{
|
||||
#if AUDIO_EN
|
||||
uint8_t msi_isnew = 0;
|
||||
struct alaw_encode_struct *alaw_encode_s = NULL;
|
||||
|
||||
struct msi *msi = msi_new("SR_ALAW_ENCODE", MAX_ALAW_ENCODE_RXBUF, &msi_isnew);
|
||||
if(msi && !msi_isnew) {
|
||||
alaw_encode_s = (struct alaw_encode_struct*)(msi->priv);
|
||||
if(alaw_encode_s) {
|
||||
if(samplerate != alaw_encode_s->samplerate) {
|
||||
ALAW_INFO("alaw_encode_init conflict!\r\n");
|
||||
goto alaw_encode_init_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(msi && msi_isnew) {
|
||||
alaw_encode_s = (struct alaw_encode_struct *)ALAW_CODE_ZALLOC(sizeof(struct alaw_encode_struct));
|
||||
if(!alaw_encode_s) {
|
||||
ALAW_INFO("alaw_encode_s malloc fail!\r\n");
|
||||
goto alaw_encode_init_err;
|
||||
}
|
||||
msi->priv = alaw_encode_s;
|
||||
msi->action = (msi_action)alaw_encode_msi_action;
|
||||
fbpool_init(&alaw_encode_s->tx_pool, MAX_ALAW_ENCODE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_ALAW_ENCODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (alaw_encode_s->tx_pool.pool)+i;
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
if(os_event_init(&alaw_encode_s->event) != RET_OK) {
|
||||
ALAW_INFO("create alaw encode event fail!\r\n");
|
||||
goto alaw_encode_init_err;
|
||||
}
|
||||
if(auenc_init->src_msi && (msi_add_output(auenc_init->src_msi, NULL, msi->name) != RET_OK)) {
|
||||
goto alaw_encode_init_err;
|
||||
}
|
||||
alaw_encode_s->msi = msi;
|
||||
alaw_encode_s->src_msi = auenc_init->src_msi;
|
||||
alaw_encode_s->samplerate = samplerate;
|
||||
alaw_encode_s->destroy_self = auenc_init->destroy_self;
|
||||
alaw_encode_s->next_status = AUCODEC_RUN;
|
||||
alaw_encode_s->current_status = AUCODEC_RUN;
|
||||
}
|
||||
else {
|
||||
ALAW_INFO("create alaw encode msi fail!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
if(msi_isnew) {
|
||||
alaw_encode_s->task_hdl = os_task_create("alaw_encode_thread", alaw_encode_thread, (void*)alaw_encode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
if(alaw_encode_s->task_hdl == NULL) {
|
||||
ALAW_INFO("create alaw encode task fail!\r\n");
|
||||
goto alaw_encode_init_err;
|
||||
}
|
||||
}
|
||||
return msi;
|
||||
|
||||
alaw_encode_init_err:
|
||||
msi_destroy(msi);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
466
sdk/app/audio_media_ctrl/amr/amr_decode.c
Normal file
466
sdk/app/audio_media_ctrl/amr/amr_decode.c
Normal file
@@ -0,0 +1,466 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/audio/audio_code/audio_code.h"
|
||||
#include "autpc_msi/autpc_msi.h"
|
||||
#include "osal_file.h"
|
||||
#include "amr_decode.h"
|
||||
|
||||
#define BUFF_SIZE 1024
|
||||
#define MAX_AMR_DECODE_TXBUF 4
|
||||
|
||||
#define AMRNB_HEADER "#!AMR\n"
|
||||
#define AMRWB_HEADER "#!AMR-WB\n"
|
||||
|
||||
enum {
|
||||
AMR_NB = 1,
|
||||
AMR_WB,
|
||||
};
|
||||
|
||||
struct amr_decode_struct {
|
||||
AUDIO_TRACK audio_track;
|
||||
struct fbpool tx_pool;
|
||||
struct os_event event;
|
||||
struct msi *msi;
|
||||
struct msi *autpc_msi;
|
||||
char *msi_name;
|
||||
void *task_hdl;
|
||||
void *amr_fp;
|
||||
uint8_t loop_mode;
|
||||
uint8_t direct_to_dac;
|
||||
uint8_t use_tpc;
|
||||
uint8_t speed;
|
||||
uint8_t pitch;
|
||||
uint8_t destroy_self;
|
||||
uint8_t amr_type;
|
||||
uint8_t next_status;
|
||||
uint8_t current_status;
|
||||
uint8_t inbuf[BUFF_SIZE];
|
||||
uint32_t buf_size;
|
||||
uint32_t buf_offset;
|
||||
};
|
||||
|
||||
static int32_t amr_file_read(struct amr_decode_struct *amr_decode_s, uint8_t *buf, uint32_t size)
|
||||
{
|
||||
int32_t read_len = 0;
|
||||
|
||||
read_len = osal_fread(buf, size, 1, amr_decode_s->amr_fp);
|
||||
return read_len;
|
||||
}
|
||||
|
||||
static void amr_decode(struct amr_decode_struct *s)
|
||||
{
|
||||
uint8_t endOfRead = 0;
|
||||
uint8_t *enc_ptr = NULL;
|
||||
int16_t *data = NULL;
|
||||
int32_t ret = 0;
|
||||
int32_t read_len = 0;
|
||||
int32_t dec_samples = 0;
|
||||
uint32_t unproc_data_size = 0;
|
||||
uint32_t enc_ptr_offset = 0;
|
||||
uint32_t bytes_to_read = 0;
|
||||
uint32_t interval_time = 0;
|
||||
struct framebuff *frame_buf = NULL;
|
||||
AUCODE_HDL *amr_dec = NULL;
|
||||
AUCODE_FRAME_INFO amr_info;
|
||||
AUDIO_TRACK *audac_fiter_track = NULL;
|
||||
|
||||
while(!s->amr_type) {
|
||||
read_len = amr_file_read(s, s->inbuf+unproc_data_size,BUFF_SIZE);
|
||||
if(read_len <= 0) {
|
||||
AMR_INFO("amr read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
|
||||
return;
|
||||
}
|
||||
s->buf_size = read_len + unproc_data_size;
|
||||
if(s->buf_size < os_strlen(AMRWB_HEADER)) {
|
||||
unproc_data_size = s->buf_size;
|
||||
os_sleep_ms(1);
|
||||
continue;
|
||||
}
|
||||
if(os_strncmp(s->inbuf, AMRWB_HEADER, os_strlen(AMRWB_HEADER)) == 0) {
|
||||
s->amr_type = AMR_WB;
|
||||
s->buf_size -= os_strlen(AMRWB_HEADER);
|
||||
s->buf_offset = 0;
|
||||
os_memcpy(s->inbuf, s->inbuf+os_strlen(AMRWB_HEADER), s->buf_size-os_strlen(AMRWB_HEADER));
|
||||
}
|
||||
else if(os_strncmp(s->inbuf, AMRNB_HEADER, os_strlen(AMRNB_HEADER)) == 0) {
|
||||
s->amr_type = AMR_NB;
|
||||
s->buf_size -= os_strlen(AMRNB_HEADER);
|
||||
s->buf_offset = 0;
|
||||
os_memcpy(s->inbuf, s->inbuf+os_strlen(AMRNB_HEADER), s->buf_size-os_strlen(AMRNB_HEADER));
|
||||
}
|
||||
else {
|
||||
AMR_INFO("amr header err!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
unproc_data_size = s->buf_size;
|
||||
if(s->amr_type == AMR_NB)
|
||||
amr_dec = audio_coder_open(AMRNB_DEC, 0, 0);
|
||||
else if(s->amr_type == AMR_WB)
|
||||
amr_dec = audio_coder_open(AMRWB_DEC, 0, 0);
|
||||
else {
|
||||
AMR_INFO("unknow amr type!\r\n");
|
||||
return;
|
||||
}
|
||||
if(!amr_dec)
|
||||
return;
|
||||
enc_ptr = s->inbuf;
|
||||
while(1) {
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
while(s->next_status == AUCODEC_PAUSE) {
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
goto amr_decode_end;
|
||||
}
|
||||
s->current_status = AUCODEC_RUN;
|
||||
if(unproc_data_size < 128 && !endOfRead) {
|
||||
bytes_to_read = BUFF_SIZE - unproc_data_size;
|
||||
if(unproc_data_size)
|
||||
os_memcpy(s->inbuf, enc_ptr+enc_ptr_offset, unproc_data_size);
|
||||
read_len = amr_file_read(s, s->inbuf+unproc_data_size, bytes_to_read);
|
||||
if(read_len <= 0) {
|
||||
AMR_INFO("amr read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
|
||||
endOfRead = 1;
|
||||
}
|
||||
else
|
||||
unproc_data_size += read_len;
|
||||
enc_ptr = s->inbuf;
|
||||
enc_ptr_offset = 0;
|
||||
}
|
||||
if(unproc_data_size > 0) {
|
||||
while(!frame_buf) {
|
||||
frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(!frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
data = (int16_t*)frame_buf->data;
|
||||
dec_samples = audio_decode_data(amr_dec, enc_ptr+enc_ptr_offset, unproc_data_size, data, &amr_info);
|
||||
if(dec_samples <= 0) {
|
||||
enc_ptr_offset += 1;
|
||||
unproc_data_size -= 1;
|
||||
msi_delete_fb(s->msi, frame_buf);;
|
||||
frame_buf = NULL;
|
||||
continue;
|
||||
}
|
||||
enc_ptr_offset += amr_info.frame_bytes;
|
||||
unproc_data_size -= amr_info.frame_bytes;
|
||||
frame_buf->len = dec_samples*2;
|
||||
frame_buf->mtype = F_AUDIO;
|
||||
frame_buf->stype = FSTYPE_AUDIO_PCM;
|
||||
s->audio_track.samplerate = amr_info.samplerate;
|
||||
ret = msi_output_fb(s->msi, frame_buf);
|
||||
if(s->use_tpc && !s->autpc_msi) {
|
||||
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
|
||||
if(s->autpc_msi == NULL) {
|
||||
goto amr_decode_end;
|
||||
}
|
||||
msi_add_output(s->msi, NULL, s->autpc_msi->name);
|
||||
if(s->direct_to_dac) {
|
||||
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
}
|
||||
AMR_DEBUG("amr decode send framebuff:%p,ret:%d\r\n",frame_buf,ret);
|
||||
msi_cmd("R_AUDAC", MSI_CMD_AUDAC, MSI_AUDAC_GET_FILTER_TRACK, (uint32_t)(&audac_fiter_track));
|
||||
if(s->direct_to_dac && (!s->use_tpc) && (audac_fiter_track != (&(s->audio_track)))) {
|
||||
interval_time = (frame_buf->len>>1)*1000/(amr_info.samplerate);
|
||||
os_sleep_ms(interval_time);
|
||||
}
|
||||
frame_buf = NULL;
|
||||
}
|
||||
else if(endOfRead) {
|
||||
goto amr_decode_end;
|
||||
}
|
||||
}
|
||||
amr_decode_end:
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
if(frame_buf) {
|
||||
msi_delete_fb(s->msi, frame_buf);
|
||||
frame_buf = NULL;
|
||||
}
|
||||
if(amr_dec)
|
||||
audio_coder_close(amr_dec);
|
||||
}
|
||||
|
||||
static void amr_decode_thread(void *d)
|
||||
{
|
||||
struct amr_decode_struct *s = (struct amr_decode_struct *)d;
|
||||
|
||||
msi_get(s->msi);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
s->msi->enable = 1;
|
||||
do {
|
||||
osal_fseek(s->amr_fp, 0);
|
||||
amr_decode(s);
|
||||
if(s->current_status == AUCODEC_EXIT) {
|
||||
break;
|
||||
}
|
||||
}while(s->loop_mode);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
os_event_set(&s->event, coder_exit_event, NULL);
|
||||
|
||||
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
|
||||
s->current_status = AUCODEC_END;
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
|
||||
if(s->next_status != AUCODEC_EXIT)
|
||||
msi_destroy(s->msi);
|
||||
|
||||
msi_put(s->msi);
|
||||
}
|
||||
|
||||
static int32_t amr_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct amr_decode_struct *amr_decode_s = (struct amr_decode_struct*)(msi->priv);
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_AUCODER:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(amr_decode_s) {
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUCODER_PAUSE:
|
||||
{
|
||||
if(amr_decode_s->current_status == AUCODEC_RUN) {
|
||||
amr_decode_s->next_status = AUCODEC_PAUSE;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CONTINUE:
|
||||
{
|
||||
if(amr_decode_s->current_status == AUCODEC_PAUSE) {
|
||||
amr_decode_s->next_status = AUCODEC_RUN;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_STATUS:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(amr_decode_s->current_status);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SPEED:
|
||||
{
|
||||
amr_decode_s->speed = (uint8_t)param2;
|
||||
ret = msi_output_cmd(amr_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(amr_decode_s->speed));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_SPEED:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(amr_decode_s->speed);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_PITCH:
|
||||
{
|
||||
amr_decode_s->pitch = (uint8_t)param2;
|
||||
ret = msi_output_cmd(amr_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(amr_decode_s->pitch));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_PITCH:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(amr_decode_s->pitch);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CLEAR_STREAM:
|
||||
{
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DIRECT_TO_DAC:
|
||||
{
|
||||
uint32_t direct_to_dac = param2;
|
||||
if(direct_to_dac && amr_decode_s->direct_to_dac == 0) {
|
||||
amr_decode_s->direct_to_dac = 1;
|
||||
if(amr_decode_s->use_tpc == 0) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(amr_decode_s->autpc_msi) {
|
||||
msi_add_output(amr_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(amr_decode_s->audio_track)));
|
||||
}
|
||||
else if(amr_decode_s->direct_to_dac == 1) {
|
||||
amr_decode_s->direct_to_dac = 0;
|
||||
if(amr_decode_s->use_tpc == 0) {
|
||||
msi_del_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(amr_decode_s->autpc_msi) {
|
||||
msi_del_output(amr_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
amr_decode_s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(amr_decode_s->audio_track)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DEINIT:
|
||||
{
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(amr_decode_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
fbpool_put(&amr_decode_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if(amr_decode_s && amr_decode_s->task_hdl) {
|
||||
amr_decode_s->next_status = AUCODEC_EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(amr_decode_s) {
|
||||
if(amr_decode_s->task_hdl) {
|
||||
os_event_wait(&amr_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
}
|
||||
for(uint32_t i=0; i<MAX_AMR_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (amr_decode_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
AMR_DECODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&amr_decode_s->tx_pool);
|
||||
if(amr_decode_s->event.hdl) {
|
||||
os_event_del(&amr_decode_s->event);
|
||||
}
|
||||
if(amr_decode_s->amr_fp) {
|
||||
osal_fclose(amr_decode_s->amr_fp);
|
||||
amr_decode_s->amr_fp = NULL;
|
||||
}
|
||||
if(amr_decode_s->autpc_msi) {
|
||||
autpc_msi_deinit(amr_decode_s->autpc_msi);
|
||||
amr_decode_s->autpc_msi = NULL;
|
||||
}
|
||||
if(amr_decode_s->msi_name) {
|
||||
AMR_DECODE_FREE(amr_decode_s->msi_name);
|
||||
amr_decode_s->msi_name = NULL;
|
||||
}
|
||||
AMR_DECODE_FREE(amr_decode_s);
|
||||
amr_decode_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *amr_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init)
|
||||
{
|
||||
#if AUDIO_EN
|
||||
char *msi_name = NULL;
|
||||
|
||||
msi_name = (char*)AMR_DECODE_ZALLOC(sizeof(char)*32);
|
||||
if(msi_name == NULL) {
|
||||
os_printf("alloc autpc msi namefail\n");
|
||||
return NULL;
|
||||
}
|
||||
os_snprintf(msi_name, 20, "SR_AMR_DECODE_""%04d", (int)(os_jiffies()));
|
||||
struct msi *msi = msi_new(msi_name, 0, NULL);
|
||||
if(msi == NULL) {
|
||||
AMR_INFO("create amr decode msi fail!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
struct amr_decode_struct *amr_decode_s = (struct amr_decode_struct*)AMR_DECODE_ZALLOC(sizeof(struct amr_decode_struct));
|
||||
if(!amr_decode_s) {
|
||||
AMR_INFO("amr_decode_s malloc fail!\r\n");
|
||||
goto amr_decode_init_err;
|
||||
}
|
||||
msi->priv = amr_decode_s;
|
||||
msi->action = (msi_action)amr_decode_msi_action;
|
||||
fbpool_init(&amr_decode_s->tx_pool, MAX_AMR_DECODE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_AMR_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (amr_decode_s->tx_pool.pool)+i;
|
||||
frame_buf->data = (uint8_t*)AMR_DECODE_MALLOC(320 * sizeof(int16_t));
|
||||
if(frame_buf->data == NULL) {
|
||||
AMR_INFO("amr decode malloc framebuff data fail!\r\n");
|
||||
goto amr_decode_init_err;
|
||||
}
|
||||
frame_buf->priv = &(amr_decode_s->audio_track);;
|
||||
}
|
||||
if(filename) {
|
||||
amr_decode_s->amr_fp = osal_fopen((const char*)filename, "rb");
|
||||
if(amr_decode_s->amr_fp == NULL) {
|
||||
AMR_INFO("open amr file %s fail!\r\n", filename);
|
||||
goto amr_decode_init_err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
AMR_INFO("arm filename is null!\r\n");
|
||||
goto amr_decode_init_err;
|
||||
}
|
||||
if(os_event_init(&amr_decode_s->event) != RET_OK) {
|
||||
AMR_INFO("create amr decode event fail!\r\n");
|
||||
goto amr_decode_init_err;
|
||||
}
|
||||
amr_decode_s->msi = msi;
|
||||
amr_decode_s->msi_name = msi_name;
|
||||
amr_decode_s->loop_mode = loop_mode;
|
||||
amr_decode_s->direct_to_dac = audec_init->direct_to_dac;
|
||||
amr_decode_s->use_tpc = audec_init->use_tpc;
|
||||
amr_decode_s->speed = audec_init->speed;
|
||||
amr_decode_s->pitch = audec_init->pitch;
|
||||
amr_decode_s->destroy_self = audec_init->destroy_self;
|
||||
amr_decode_s->audio_track.priority = audec_init->priority;
|
||||
amr_decode_s->audio_track.track_type = audec_init->track_type;
|
||||
amr_decode_s->next_status = AUCODEC_RUN;
|
||||
amr_decode_s->current_status = AUCODEC_RUN;
|
||||
if(audec_init->direct_to_dac && !amr_decode_s->use_tpc) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
#if AMRNB_DEC_CTRL == AUCODER_RUN_IN_CPU1
|
||||
amr_decode_s->task_hdl = os_task_create("amr_decode_thread", amr_decode_thread, (void*)amr_decode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
#else
|
||||
amr_decode_s->task_hdl = os_task_create("amr_decode_thread", amr_decode_thread, (void*)amr_decode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 4096);
|
||||
#endif
|
||||
if(amr_decode_s->task_hdl == NULL) {
|
||||
AMR_INFO("create amr decode task fail!\r\n");
|
||||
goto amr_decode_init_err;
|
||||
}
|
||||
return msi;
|
||||
|
||||
amr_decode_init_err:
|
||||
msi_destroy(msi);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
24
sdk/app/audio_media_ctrl/amr/amr_decode.h
Normal file
24
sdk/app/audio_media_ctrl/amr/amr_decode.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef _AMR__DECODE_MSI_H_
|
||||
#define _AMR__DECODE_MSI_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "audio_code_ctrl.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define AMR_DECODE_MALLOC av_psram_malloc
|
||||
#define AMR_DECODE_ZALLOC av_psram_zalloc
|
||||
#define AMR_DECODE_FREE av_psram_free
|
||||
#else
|
||||
#define AMR_DECODE_MALLOC av_malloc
|
||||
#define AMR_DECODE_ZALLOC av_zalloc
|
||||
#define AMR_DECODE_FREE av_free
|
||||
#endif
|
||||
|
||||
#define AMR_DEBUG(fmt, args...) //os_printf(fmt, ##args)
|
||||
#define AMR_INFO os_printf
|
||||
|
||||
struct msi *amr_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init);
|
||||
|
||||
#endif
|
||||
130
sdk/app/audio_media_ctrl/audio_code_ctrl.c
Normal file
130
sdk/app/audio_media_ctrl/audio_code_ctrl.c
Normal file
@@ -0,0 +1,130 @@
|
||||
#include "basic_include.h"
|
||||
#include "audio_code_ctrl.h"
|
||||
#include "aac_code.h"
|
||||
#include "alaw_code.h"
|
||||
#include "amr_decode.h"
|
||||
#include "mp3_decode.h"
|
||||
#include "opus_code.h"
|
||||
#include "wave_code.h"
|
||||
|
||||
struct msi *audio_encode_init(uint32_t coder, uint32_t samplerate, AUENC_INIT *auenc_init)
|
||||
{
|
||||
struct msi *msi = NULL;
|
||||
switch(coder) {
|
||||
case AAC_ENC:
|
||||
msi = aac_encode_init(NULL, samplerate, 0, auenc_init);
|
||||
break;
|
||||
case ALAW_ENC:
|
||||
msi = alaw_encode_init(samplerate, auenc_init);
|
||||
break;
|
||||
case OPUS_ENC:
|
||||
msi = opus_encode_init(samplerate, auenc_init);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
|
||||
struct msi *audio_decode_init(uint32_t coder, uint32_t samplerate, AUDEC_INIT *audec_init)
|
||||
{
|
||||
struct msi *msi = NULL;
|
||||
switch(coder) {
|
||||
case AAC_DEC:
|
||||
msi = aac_decode_init(NULL, 0, audec_init);
|
||||
break;
|
||||
case ALAW_DEC:
|
||||
msi = alaw_decode_init(audec_init);
|
||||
break;
|
||||
case AMRNB_DEC:
|
||||
case AMRWB_DEC:
|
||||
msi = amr_decode_init(NULL, 0, audec_init);
|
||||
break;
|
||||
case MP3_DEC:
|
||||
msi = mp3_decode_init(NULL, 0, audec_init);
|
||||
break;
|
||||
case OPUS_DEC:
|
||||
msi = opus_decode_init(samplerate, audec_init);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
|
||||
int32_t audio_code_set_src_msi(struct msi *msi, struct msi *src_msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_SET_SRCMSI, (uint32_t)src_msi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_encode_deinit(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_DEINIT, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_decode_deinit(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_DEINIT, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_encode_set_bitrate(struct msi *msi, uint32_t bitrate)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_SET_BITRATE, bitrate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_code_continue(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_CONTINUE, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_code_pause(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_PAUSE, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_code_clear(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_CLEAR_STREAM, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_code_add_output(struct msi *msi, const char *msi_name)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_add_output(msi, NULL, msi_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_code_del_output(struct msi *msi, const char *msi_name)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_del_output(msi, NULL, msi_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_code_direct_to_dac(struct msi *msi, uint32_t direct_to_dac)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_DIRECT_TO_DAC, direct_to_dac);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_code_get_status(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_GET_STATUS, (uint32_t)(&ret));
|
||||
return ret;
|
||||
}
|
||||
85
sdk/app/audio_media_ctrl/audio_code_ctrl.h
Normal file
85
sdk/app/audio_media_ctrl/audio_code_ctrl.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#ifndef _AUDIO_CODER_CTRL_H_
|
||||
#define _AUDIO_CODER_CTRL_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/audio/audio_code/audio_code.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
|
||||
#define PACKET_LOSS_CONCEALMENT -1
|
||||
#define OUTPUT_MUTE_DATA -2
|
||||
#define DECODE_ADD_FADE_IN -3
|
||||
#define DECODE_ADD_FADE_OUT -4
|
||||
|
||||
typedef struct {
|
||||
int32_t decode_operation;
|
||||
} AUDECODER_OPERATION;
|
||||
|
||||
typedef struct {
|
||||
uint16_t nsamples;
|
||||
uint16_t time_interval;
|
||||
uint32_t samplerate;
|
||||
} AUDIO_INFO;
|
||||
|
||||
typedef struct {
|
||||
uint8_t track_type;
|
||||
uint8_t priority;
|
||||
uint32_t samplerate;
|
||||
} AUDIO_TRACK;
|
||||
|
||||
typedef struct {
|
||||
struct msi *src_msi;
|
||||
uint8_t destroy_self;
|
||||
} AUENC_INIT;
|
||||
|
||||
typedef struct {
|
||||
struct msi *src_msi;
|
||||
uint8_t track_type;
|
||||
uint8_t priority;
|
||||
uint8_t direct_to_dac;
|
||||
uint8_t use_tpc;
|
||||
uint8_t speed;
|
||||
uint8_t pitch;
|
||||
uint8_t destroy_self;
|
||||
} AUDEC_INIT;
|
||||
|
||||
enum {
|
||||
CALL_TRACK = 1,
|
||||
MEDIA_TRACK,
|
||||
BELL_TRACK,
|
||||
};
|
||||
|
||||
enum {
|
||||
AUCODEC_RUN,
|
||||
AUCODEC_PAUSE,
|
||||
AUCODEC_END,
|
||||
AUCODEC_EXIT,
|
||||
};
|
||||
|
||||
enum {
|
||||
coder_clear_event = BIT(0),
|
||||
coder_clear_finish_event = BIT(1),
|
||||
coder_exit_event = BIT(2),
|
||||
};
|
||||
|
||||
enum {
|
||||
play_disabled = 0x00,
|
||||
play_interruptible = 0x40,
|
||||
play_nonInterruptible = 0x80,
|
||||
};
|
||||
|
||||
struct msi *audio_encode_init(uint32_t coder, uint32_t samplerate, AUENC_INIT *auenc_init);
|
||||
struct msi *audio_decode_init(uint32_t coder, uint32_t samplerate, AUDEC_INIT *audec_init);
|
||||
int32_t audio_code_set_src_msi(struct msi *msi, struct msi *src_msi);
|
||||
int32_t audio_encode_deinit(struct msi *msi);
|
||||
int32_t audio_decode_deinit(struct msi *msi);
|
||||
int32_t audio_encode_set_bitrate(struct msi *msi, uint32_t bitrate);
|
||||
int32_t audio_code_continue(struct msi *msi);
|
||||
int32_t audio_code_pause(struct msi *msi);
|
||||
int32_t audio_code_clear(struct msi *msi);
|
||||
int32_t audio_code_add_output(struct msi *msi, const char *msi_name);
|
||||
int32_t audio_code_del_output(struct msi *msi, const char *msi_name);
|
||||
int32_t audio_code_direct_to_dac(struct msi *msi, uint32_t direct_to_dac);
|
||||
int32_t audio_code_get_status(struct msi *msi);
|
||||
|
||||
#endif
|
||||
278
sdk/app/audio_media_ctrl/audio_media_ctrl.c
Normal file
278
sdk/app/audio_media_ctrl/audio_media_ctrl.c
Normal file
@@ -0,0 +1,278 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "fatfs/osal_file.h"
|
||||
#include "audio_media_ctrl.h"
|
||||
#include "audio_msi/audio_adc.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "aac/aac_code.h"
|
||||
#include "amr/amr_decode.h"
|
||||
#include "mp3/mp3_decode.h"
|
||||
#include "wave/wave_code.h"
|
||||
|
||||
#define RECORD_DIR "0:/audio"
|
||||
#define MAX(a, b) ((a) > (b) ? a : b)
|
||||
|
||||
struct audio_record_struct {
|
||||
char filename[30];
|
||||
uint8_t record_format;
|
||||
int32_t record_time; //seconds
|
||||
uint8_t is_running;
|
||||
uint32_t sampleRate;
|
||||
struct msi *msi;
|
||||
};
|
||||
static struct audio_record_struct *audio_record_s = NULL;
|
||||
|
||||
static char *get_file_extension(char *filename) {
|
||||
char *dot = os_strrchr((const char*)filename, '.');
|
||||
if (!dot || dot == filename) {
|
||||
return filename;
|
||||
}
|
||||
return dot + 1;
|
||||
}
|
||||
|
||||
static uint32_t a2i(char *str)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
uint32_t indx = 0;
|
||||
char str_buf[32];
|
||||
memset(str_buf, 0, 32);
|
||||
while (str[indx] != '\0')
|
||||
{
|
||||
if (str[indx] == '.')
|
||||
break;
|
||||
str_buf[indx] = str[indx];
|
||||
indx++;
|
||||
}
|
||||
indx = 0;
|
||||
while (str_buf[indx] != '\0')
|
||||
{
|
||||
if (str_buf[indx] >= '0' && str_buf[indx] <= '9')
|
||||
{
|
||||
ret = ret * 10 + str_buf[indx] - '0';
|
||||
}
|
||||
indx++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void creat_audio_filename(char *dir_name)
|
||||
{
|
||||
DIR dir;
|
||||
FRESULT ret;
|
||||
FILINFO finfo;
|
||||
int indx = 0;
|
||||
|
||||
ret = f_opendir(&dir, dir_name);
|
||||
if (ret != FR_OK)
|
||||
{
|
||||
f_mkdir(dir_name);
|
||||
f_opendir(&dir, dir_name);
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
ret = f_readdir(&dir, &finfo);
|
||||
if (ret != FR_OK || finfo.fname[0] == 0)
|
||||
break;
|
||||
indx = MAX(indx, a2i(finfo.fname));
|
||||
}
|
||||
f_closedir(&dir);
|
||||
indx++;
|
||||
#if DEFAULT_RECORD_FORMAT == RECORD_AAC
|
||||
os_sprintf((char*)(audio_record_s->filename), "%s/a%d.%s", dir_name, indx, "aac");
|
||||
#else
|
||||
os_sprintf((char*)(audio_record_s->filename), "%s/a%d.%s", dir_name, indx, "wav");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void audio_file_record_thread(void *d)
|
||||
{
|
||||
uint8_t status = AUCODEC_EXIT;
|
||||
uint32_t count = 0;
|
||||
uint32_t start_time = 0;
|
||||
AUENC_INIT auenc_init;
|
||||
|
||||
auenc_init.destroy_self = 0;
|
||||
auenc_init.src_msi = get_auadc_msi(AUSYS_AUAD);
|
||||
os_printf("start record file:%s\n",audio_record_s->filename);
|
||||
if(audio_record_s->record_format == WAV) {
|
||||
audio_record_s->msi = wave_encode_init(audio_record_s->filename, audio_record_s->sampleRate, &auenc_init);
|
||||
}
|
||||
else if(audio_record_s->record_format == AAC) {
|
||||
audio_record_s->msi = aac_encode_init(audio_record_s->filename, audio_record_s->sampleRate, 1, &auenc_init);
|
||||
}
|
||||
if(audio_record_s->msi == NULL) {
|
||||
os_printf("audio encode init err!\r\n");
|
||||
goto audio_record_thread_end;
|
||||
}
|
||||
start_time = os_jiffies();
|
||||
while(audio_record_s->is_running && (audio_record_s->record_time < 0 ||
|
||||
(os_jiffies()-start_time)/1000 < audio_record_s->record_time)) {
|
||||
status = AUCODEC_END;
|
||||
msi_do_cmd(audio_record_s->msi, MSI_CMD_AUCODER, MSI_AUCODER_GET_STATUS, (uint32_t)(&status));
|
||||
if(status == AUCODEC_END) {
|
||||
os_printf("record err!\r\n");
|
||||
goto audio_record_thread_end;
|
||||
}
|
||||
count++;
|
||||
if(count % 1000 == 0)
|
||||
{
|
||||
os_printf("%s\t\trecord time:%d\r\n",__FUNCTION__,os_jiffies()-start_time);
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
audio_record_thread_end:
|
||||
msi_do_cmd(audio_record_s->msi, MSI_CMD_AUCODER, MSI_AUCODER_DEINIT, 1);
|
||||
av_free(audio_record_s);
|
||||
audio_record_s = NULL;
|
||||
os_printf("audio record thread end!\r\n");
|
||||
}
|
||||
|
||||
int32_t audio_file_record_pause(void)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
if(audio_record_s && audio_record_s->is_running) {
|
||||
ret = msi_do_cmd(audio_record_s->msi, MSI_CMD_AUCODER, MSI_AUCODER_PAUSE, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_file_record_continue(void)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
if(audio_record_s && audio_record_s->is_running) {
|
||||
ret = msi_do_cmd(audio_record_s->msi, MSI_CMD_AUCODER, MSI_AUCODER_CONTINUE, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_file_record_stop(void)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
if(audio_record_s) {
|
||||
audio_record_s->is_running = 0;
|
||||
while(audio_record_s && ((++count) < 1000))
|
||||
os_sleep_ms(1);
|
||||
return RET_OK;
|
||||
}
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
int32_t audio_file_record_status(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
if(audio_record_s && audio_record_s->is_running) {
|
||||
msi_do_cmd(audio_record_s->msi, MSI_CMD_AUCODER, MSI_AUCODER_GET_STATUS, (uint32_t)(&ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_file_record_init(char *filename, uint32_t sampleRate, int32_t record_time)
|
||||
{
|
||||
uint8_t *file_extension = NULL;
|
||||
|
||||
if(audio_record_s) {
|
||||
os_printf("%s err,already recording!\r\n", __FUNCTION__);
|
||||
return RET_ERR;
|
||||
}
|
||||
else {
|
||||
audio_record_s = (struct audio_record_struct *)av_zalloc(sizeof(struct audio_record_struct));
|
||||
if(!audio_record_s) {
|
||||
os_printf("malloc audio_record_s fail!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
}
|
||||
os_memset(audio_record_s->filename, 0, sizeof(audio_record_struct));
|
||||
if(filename) {
|
||||
file_extension = (uint8_t*)get_file_extension((char*)filename);
|
||||
if((os_strncmp(file_extension, "wav", 3)==0) || (os_strncmp(file_extension, "WAV", 3)==0)) {
|
||||
audio_record_s->record_format = WAV;
|
||||
}
|
||||
else if((os_strncmp(file_extension, "aac", 3)==0) || (os_strncmp(file_extension, "AAC", 3)==0)) {
|
||||
audio_record_s->record_format = AAC;
|
||||
}
|
||||
else {
|
||||
os_printf("Unsupported audio record format!\r\n");
|
||||
av_free(audio_record_s);
|
||||
audio_record_s = NULL;
|
||||
return RET_ERR;
|
||||
}
|
||||
os_memcpy(audio_record_s->filename, filename, os_strlen(filename));
|
||||
}
|
||||
else {
|
||||
#if DEFAULT_RECORD_FORMAT == RECORD_AAC
|
||||
audio_record_s->record_format = AAC;
|
||||
creat_audio_filename(RECORD_DIR);
|
||||
#else
|
||||
audio_record_s->record_format = WAV;
|
||||
creat_audio_filename(RECORD_DIR);
|
||||
#endif
|
||||
}
|
||||
audio_record_s->sampleRate = sampleRate;
|
||||
audio_record_s->record_time = record_time;
|
||||
audio_record_s->is_running = 1;
|
||||
os_task_create("audio_file_record_thread", audio_file_record_thread, audio_record_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32_t audio_file_play_pause(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_PAUSE, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_file_play_continue(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_CONTINUE, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_file_play_stop(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
ret = msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_DEINIT, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_file_play_status(struct msi *msi)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
msi_do_cmd(msi, MSI_CMD_AUCODER, MSI_AUCODER_GET_STATUS, (uint32_t)(&ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *audio_file_play_init(char *filename, uint8_t play_mode, AUDEC_INIT *audec_init)
|
||||
{
|
||||
uint8_t *file_extension = NULL;
|
||||
uint8_t audio_format = 0;
|
||||
struct msi *msi = NULL;
|
||||
|
||||
if(filename) {
|
||||
file_extension = (uint8_t*)get_file_extension((char*)filename);
|
||||
if((os_strncmp(file_extension, "wav", 3)==0) || (os_strncmp(file_extension, "WAV", 3)==0))
|
||||
audio_format = WAV;
|
||||
else if((os_strncmp(file_extension, "mp3", 3)==0) || (os_strncmp(file_extension, "MP3", 3)==0))
|
||||
audio_format = MP3;
|
||||
else if((os_strncmp(file_extension, "amr", 3)==0) || (os_strncmp(file_extension, "AMR", 3)==0))
|
||||
audio_format = AMR;
|
||||
else if((os_strncmp(file_extension, "aac", 3)==0) || (os_strncmp(file_extension, "AAC", 3)==0))
|
||||
audio_format = AAC;
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
os_printf("enter audio filename\n");
|
||||
return NULL;
|
||||
}
|
||||
switch(audio_format) {
|
||||
case WAV:msi = wave_decode_init(filename, (play_mode==2), audec_init);break;
|
||||
case MP3:msi = mp3_decode_init(filename, (play_mode==2), audec_init);break;
|
||||
case AMR:msi = amr_decode_init(filename, (play_mode==2), audec_init);break;
|
||||
case AAC:msi = aac_decode_init(filename, (play_mode==2), audec_init);break;
|
||||
default:break;
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
43
sdk/app/audio_media_ctrl/audio_media_ctrl.h
Normal file
43
sdk/app/audio_media_ctrl/audio_media_ctrl.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef _AUDIO_MEDIA_CTRL_H_
|
||||
#define _AUDIO_MEDIA_CTRL_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "audio_code_ctrl.h"
|
||||
|
||||
enum {
|
||||
WAV = 1,
|
||||
MP3,
|
||||
AMR,
|
||||
AAC,
|
||||
};
|
||||
|
||||
enum {
|
||||
NORMAL_PLAY = 1,
|
||||
LOOP_PLAY,
|
||||
};
|
||||
|
||||
#define RECORD_WAV 1
|
||||
#define RECORD_AAC 2
|
||||
|
||||
#define DEFAULT_RECORD_FORMAT RECORD_AAC
|
||||
|
||||
typedef struct {
|
||||
uint8_t filename[30];
|
||||
uint8_t record_format;
|
||||
uint8_t is_running;
|
||||
int32_t record_time; //seconds
|
||||
uint32_t sampleRate;
|
||||
} audio_record_struct;
|
||||
|
||||
int32_t audio_file_record_pause(void);
|
||||
int32_t audio_file_record_continue(void);
|
||||
int32_t audio_file_record_stop(void);
|
||||
int32_t audio_file_record_status(struct msi *msi);
|
||||
int32_t audio_file_record_init(char *filename, uint32_t sampleRate, int32_t record_time);
|
||||
int32_t audio_file_play_pause(struct msi *msi);
|
||||
int32_t audio_file_play_continue(struct msi *msi);
|
||||
int32_t audio_file_play_stop(struct msi *msi);
|
||||
int32_t audio_file_play_status(struct msi *msi);
|
||||
struct msi *audio_file_play_init(char *filename, uint8_t play_mode, AUDEC_INIT *audec_init);
|
||||
|
||||
#endif
|
||||
768
sdk/app/audio_media_ctrl/mp3/mp3_decode.c
Normal file
768
sdk/app/audio_media_ctrl/mp3/mp3_decode.c
Normal file
@@ -0,0 +1,768 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/audio/audio_code/audio_code.h"
|
||||
#include "autpc_msi/autpc_msi.h"
|
||||
#include "osal_file.h"
|
||||
#include "mp3_decode.h"
|
||||
#include "mp3_getInfo.h"
|
||||
|
||||
#define BUFF_SIZE 2048
|
||||
#define MAX_MP3_DECODE_RXBUF 4
|
||||
#define MAX_MP3_DECODE_TXBUF 8
|
||||
|
||||
struct mp3_decode_struct {
|
||||
AUDIO_TRACK audio_track;
|
||||
struct fbpool tx_pool;
|
||||
struct os_event event;
|
||||
struct msi *msi;
|
||||
struct msi *src_msi;
|
||||
struct msi *autpc_msi;
|
||||
char *msi_name;
|
||||
void *task_hdl;
|
||||
void *mp3_fp;
|
||||
uint8_t mp3_filename[20];
|
||||
uint8_t loop_mode;
|
||||
uint8_t direct_to_dac;
|
||||
uint8_t use_tpc;
|
||||
uint8_t speed;
|
||||
uint8_t pitch;
|
||||
uint8_t destroy_self;
|
||||
uint8_t get_first_frame;
|
||||
uint8_t next_status;
|
||||
uint8_t current_status;
|
||||
uint8_t inbuf[BUFF_SIZE];
|
||||
int16_t dec_buf[1152*2];
|
||||
uint32_t file_size;
|
||||
uint32_t buf_offset;
|
||||
uint32_t buf_size;
|
||||
CUR_MP3_INFO *cur_mp3_info;
|
||||
};
|
||||
|
||||
static int32_t mp3_file_read(struct mp3_decode_struct *mp3_decode_s, uint8_t *buf, uint32_t size)
|
||||
{
|
||||
int32_t read_len = 0;
|
||||
|
||||
read_len = osal_fread(buf, size, 1, mp3_decode_s->mp3_fp);
|
||||
return read_len;
|
||||
}
|
||||
|
||||
static void mp3_file_decode(struct mp3_decode_struct *s)
|
||||
{
|
||||
uint8_t endOfRead = 0;
|
||||
uint8_t *enc_ptr = NULL;
|
||||
int16_t *data = NULL;
|
||||
int32_t ret = 0;
|
||||
int32_t dec_samples = 0;
|
||||
int32_t read_len = 0;
|
||||
int32_t unproc_data_size = 0;
|
||||
int32_t ID3V2_offset = 0;
|
||||
uint32_t ID3V2_len = 0;
|
||||
uint32_t enc_ptr_offset = 0;
|
||||
uint32_t bytes_to_read = 0;
|
||||
uint32_t interval_time = 0;
|
||||
struct framebuff *frame_buf = NULL;
|
||||
AUCODE_HDL *mp3_dec = NULL;
|
||||
AUCODE_FRAME_INFO mp3_info;
|
||||
AUDIO_TRACK *audac_fiter_track = NULL;
|
||||
|
||||
while(!s->get_first_frame) {
|
||||
bytes_to_read = BUFF_SIZE - unproc_data_size;
|
||||
read_len = mp3_file_read(s, s->inbuf+unproc_data_size,bytes_to_read);
|
||||
if(read_len <= 0) {
|
||||
MP3_INFO("mp3 read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
|
||||
goto mp3_decode_end;
|
||||
}
|
||||
s->buf_size = read_len + unproc_data_size;
|
||||
if(os_strncmp(s->inbuf, "ID3", 3) == 0) {
|
||||
if (s->buf_size < 10) {
|
||||
unproc_data_size = s->buf_size;
|
||||
os_sleep_ms(1);
|
||||
continue;
|
||||
}
|
||||
ID3V2_len = (s->inbuf[6]&0x7F)*0x200000+ (s->inbuf[7]&0x7F)*0x4000 +
|
||||
(s->inbuf[8]&0x7F)*0x80 +(s->inbuf[9]&0x7F);
|
||||
ID3V2_offset = (ID3V2_len+10);
|
||||
while(ID3V2_offset >= s->buf_size) {
|
||||
os_sleep_ms(1);
|
||||
ID3V2_offset -= s->buf_size;
|
||||
read_len = mp3_file_read(s, s->inbuf,BUFF_SIZE);
|
||||
if(read_len <= 0) {
|
||||
MP3_INFO("mp3 read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
|
||||
goto mp3_decode_end;
|
||||
}
|
||||
s->buf_size = read_len;
|
||||
}
|
||||
if(ID3V2_offset) {
|
||||
s->buf_size -= ID3V2_offset;
|
||||
os_memcpy(s->inbuf, s->inbuf+ID3V2_offset, s->buf_size);
|
||||
}
|
||||
if(s->buf_size <= 1) {
|
||||
os_sleep_ms(1);
|
||||
unproc_data_size = s->buf_size;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint32_t i=0; i<(s->buf_size-1); i++) {
|
||||
if( ( (s->inbuf[i] << 8) | (s->inbuf[i+1] & 0xE0) ) == 0xFFE0 ) {
|
||||
s->get_first_frame = 1;
|
||||
unproc_data_size = s->buf_size - i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!s->get_first_frame) {
|
||||
unproc_data_size = 1;
|
||||
s->inbuf[0] = s->inbuf[s->buf_size-1];
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
mp3_dec = audio_coder_open(MP3_DEC, 0, 0);
|
||||
if(mp3_dec == NULL)
|
||||
return;
|
||||
enc_ptr = s->inbuf;
|
||||
while(1) {
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
while(s->next_status == AUCODEC_PAUSE) {
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
goto mp3_decode_end;
|
||||
}
|
||||
s->current_status = AUCODEC_RUN;
|
||||
if(unproc_data_size < BUFF_SIZE && !endOfRead) {
|
||||
bytes_to_read = BUFF_SIZE - unproc_data_size;
|
||||
if(unproc_data_size)
|
||||
os_memcpy(s->inbuf, enc_ptr+enc_ptr_offset, unproc_data_size);
|
||||
read_len = mp3_file_read(s, s->inbuf+unproc_data_size, bytes_to_read);
|
||||
if(read_len <= 0) {
|
||||
MP3_INFO("mp3 read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
|
||||
endOfRead = 1;
|
||||
}
|
||||
else
|
||||
unproc_data_size += read_len;
|
||||
enc_ptr = s->inbuf;
|
||||
enc_ptr_offset = 0;
|
||||
}
|
||||
if(unproc_data_size > 0) {
|
||||
while(!frame_buf) {
|
||||
frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(!frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
data = (int16_t*)frame_buf->data;
|
||||
dec_samples = audio_decode_data(mp3_dec, enc_ptr+enc_ptr_offset, unproc_data_size, s->dec_buf, &mp3_info);
|
||||
if(dec_samples <= 0) {
|
||||
enc_ptr_offset += 1;
|
||||
unproc_data_size -= 1;
|
||||
msi_delete_fb(s->msi, frame_buf);
|
||||
frame_buf = NULL;
|
||||
continue;
|
||||
}
|
||||
if(mp3_info.channels == 2) {
|
||||
for(uint32_t i=0; i<dec_samples; i++)
|
||||
data[i] = s->dec_buf[2*i];
|
||||
}
|
||||
else {
|
||||
for(uint32_t i=0; i<dec_samples; i++)
|
||||
data[i] = s->dec_buf[i];
|
||||
}
|
||||
enc_ptr_offset += mp3_info.frame_bytes;
|
||||
unproc_data_size -= mp3_info.frame_bytes;
|
||||
frame_buf->len = dec_samples*2;
|
||||
frame_buf->mtype = F_AUDIO;
|
||||
frame_buf->stype = FSTYPE_AUDIO_PCM;
|
||||
s->audio_track.samplerate = mp3_info.samplerate;
|
||||
if(s->use_tpc && !s->autpc_msi) {
|
||||
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
|
||||
if(s->autpc_msi == NULL) {
|
||||
goto mp3_decode_end;
|
||||
}
|
||||
if(s->direct_to_dac) {
|
||||
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_add_output(s->msi, NULL, s->autpc_msi->name);
|
||||
}
|
||||
ret = msi_output_fb(s->msi, frame_buf);
|
||||
MP3_DEBUG("mp3 decode send framebuff:%p,ret:%d\r\n",frame_buf,ret);
|
||||
msi_cmd("R_AUDAC", MSI_CMD_AUDAC, MSI_AUDAC_GET_FILTER_TRACK, (uint32_t)(&audac_fiter_track));
|
||||
if(s->direct_to_dac && (!s->use_tpc) && (audac_fiter_track != (&(s->audio_track)))) {
|
||||
interval_time = (frame_buf->len>>1)*1000/(mp3_info.samplerate);
|
||||
os_sleep_ms(interval_time);
|
||||
}
|
||||
frame_buf = NULL;
|
||||
}
|
||||
else if(endOfRead){
|
||||
goto mp3_decode_end;
|
||||
}
|
||||
}
|
||||
mp3_decode_end:
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
if(frame_buf) {
|
||||
msi_delete_fb(s->msi, frame_buf);
|
||||
frame_buf = NULL;
|
||||
}
|
||||
if(mp3_dec) {
|
||||
audio_coder_close(mp3_dec);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_frame_buf(struct msi *msi, struct framebuff * frame_buf)
|
||||
{
|
||||
msi_delete_fb(NULL, frame_buf);
|
||||
frame_buf = NULL;
|
||||
while(!frame_buf) {
|
||||
frame_buf = msi_get_fb(msi, 0);
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void mp3_msi_decode(struct mp3_decode_struct *s)
|
||||
{
|
||||
uint8_t clear_finish = 1;
|
||||
uint8_t find_ID3 = 0;
|
||||
uint8_t endOfRead = 0;
|
||||
uint8_t *recv_data = NULL;
|
||||
int16_t *send_data = NULL;
|
||||
uint8_t *enc_ptr = NULL;
|
||||
int32_t ret = 0;
|
||||
int32_t data_len = 0;
|
||||
int32_t dec_samples = 0;
|
||||
int32_t unproc_data_size = 0;
|
||||
int32_t ID3V2_offset = 0;
|
||||
uint32_t ID3V2_len = 0;
|
||||
uint32_t bytes_to_copy = 0;
|
||||
uint32_t recv_data_offset = 0;
|
||||
uint32_t enc_ptr_offset = 0;
|
||||
uint32_t clear_flag = 0;
|
||||
struct framebuff *recv_frame_buf = NULL;
|
||||
struct framebuff *send_frame_buf = NULL;
|
||||
AUCODE_HDL *mp3_dec = NULL;
|
||||
AUCODE_FRAME_INFO mp3_info;
|
||||
|
||||
mp3_dec = audio_coder_open(MP3_DEC, 0, 0);
|
||||
if(mp3_dec == NULL)
|
||||
return;
|
||||
enc_ptr = s->inbuf;
|
||||
while(1) {
|
||||
get_recv_frame_buf_again:
|
||||
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
|
||||
if(clear_flag & coder_clear_event) {
|
||||
clear_flag = 0;
|
||||
clear_finish = 0;
|
||||
}
|
||||
recv_frame_buf = msi_get_fb(s->msi, 0);
|
||||
if(recv_frame_buf) {
|
||||
data_len = recv_frame_buf->len;
|
||||
recv_data = recv_frame_buf->data;
|
||||
recv_data_offset = 0;
|
||||
if(data_len <= 0)
|
||||
endOfRead = 1;
|
||||
if(!s->get_first_frame) {
|
||||
if(data_len <= 0)
|
||||
goto mp3_decode_end;
|
||||
if((os_strncmp(recv_data, "ID3", 3) == 0) && !find_ID3) {
|
||||
ID3V2_len = (recv_data[6]&0x7F)*0x200000+ (recv_data[7]&0x7F)*0x4000 +
|
||||
(recv_data[8]&0x7F)*0x80 +(recv_data[9]&0x7F);
|
||||
ID3V2_offset = (ID3V2_len+10);
|
||||
while(ID3V2_offset >= data_len) {
|
||||
ID3V2_offset -= data_len;
|
||||
update_frame_buf(s->msi, recv_frame_buf);
|
||||
data_len = recv_frame_buf->len;
|
||||
if(data_len <= 0)
|
||||
goto mp3_decode_end;
|
||||
}
|
||||
recv_data_offset = ID3V2_offset;
|
||||
data_len -= ID3V2_offset;
|
||||
if(data_len <= 1) {
|
||||
os_memcpy(s->inbuf, recv_data+recv_data_offset, data_len);
|
||||
s->buf_size = data_len;
|
||||
unproc_data_size = data_len;
|
||||
update_frame_buf(s->msi, recv_frame_buf);
|
||||
recv_data_offset = 0;
|
||||
data_len = recv_frame_buf->len;
|
||||
if(data_len <= 0)
|
||||
goto mp3_decode_end;
|
||||
}
|
||||
}
|
||||
find_ID3 = 1;
|
||||
while(data_len) {
|
||||
bytes_to_copy = data_len>(BUFF_SIZE-unproc_data_size)?(BUFF_SIZE-unproc_data_size):data_len;
|
||||
os_memcpy(s->inbuf+unproc_data_size, recv_data+recv_data_offset, bytes_to_copy);
|
||||
s->buf_size += bytes_to_copy;
|
||||
data_len -= bytes_to_copy;
|
||||
recv_data_offset += bytes_to_copy;
|
||||
for(uint32_t i=0; i<(s->buf_size-1); i++) {
|
||||
if( ( (s->inbuf[i] << 8) | (s->inbuf[i+1] & 0xE0) ) == 0xFFE0 ) {
|
||||
s->get_first_frame = 1;
|
||||
unproc_data_size = s->buf_size - i;
|
||||
s->buf_size -= i;
|
||||
enc_ptr_offset += i;
|
||||
goto mp3_get_first_frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!s->get_first_frame) {
|
||||
unproc_data_size = 1;
|
||||
s->inbuf[0] = s->inbuf[s->buf_size-1];
|
||||
s->buf_size = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(clear_finish == 0) {
|
||||
clear_finish = 1;
|
||||
os_event_set(&s->event, coder_clear_finish_event, NULL);
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
mp3_get_first_frame:
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
goto mp3_decode_end;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(recv_frame_buf)
|
||||
msi_delete_fb(s->msi, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
enc_ptr_offset = 0;
|
||||
unproc_data_size = 0;
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
audio_coder_close(mp3_dec);
|
||||
if(send_frame_buf) {
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
}
|
||||
send_frame_buf = NULL;
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
mp3_dec = audio_coder_open(MP3_DEC, 0, 0);
|
||||
if(mp3_dec == NULL)
|
||||
return;
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
}
|
||||
else
|
||||
s->current_status = AUCODEC_RUN;
|
||||
if(clear_finish == 0) {
|
||||
if(recv_frame_buf)
|
||||
msi_delete_fb(s->msi, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
enc_ptr_offset = 0;
|
||||
unproc_data_size = 0;
|
||||
continue;
|
||||
}
|
||||
while((data_len>0) || (unproc_data_size>0)) {
|
||||
if((data_len) >= (BUFF_SIZE-unproc_data_size)) {
|
||||
os_memcpy(enc_ptr, enc_ptr+enc_ptr_offset, unproc_data_size);
|
||||
bytes_to_copy = BUFF_SIZE - unproc_data_size;
|
||||
os_memcpy(enc_ptr+unproc_data_size, recv_data+recv_data_offset, bytes_to_copy);
|
||||
data_len -= bytes_to_copy;
|
||||
recv_data_offset += bytes_to_copy;
|
||||
enc_ptr_offset = 0;
|
||||
unproc_data_size += bytes_to_copy;
|
||||
}
|
||||
else if(!endOfRead) {
|
||||
bytes_to_copy = data_len;
|
||||
if(bytes_to_copy) {
|
||||
os_memcpy(enc_ptr, enc_ptr+enc_ptr_offset, unproc_data_size);
|
||||
os_memcpy(enc_ptr+unproc_data_size, recv_data+recv_data_offset, bytes_to_copy);
|
||||
data_len -= bytes_to_copy;
|
||||
recv_data_offset += bytes_to_copy;
|
||||
enc_ptr_offset = 0;
|
||||
unproc_data_size += bytes_to_copy;
|
||||
}
|
||||
msi_delete_fb(NULL, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
goto get_recv_frame_buf_again;
|
||||
}
|
||||
while(!send_frame_buf) {
|
||||
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(!send_frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
send_data = (int16_t*)send_frame_buf->data;
|
||||
dec_samples = audio_decode_data(mp3_dec, enc_ptr+enc_ptr_offset, unproc_data_size, s->dec_buf, &mp3_info);
|
||||
if(dec_samples <= 0) {
|
||||
enc_ptr_offset += 1;
|
||||
unproc_data_size -= 1;
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
continue;
|
||||
}
|
||||
if(mp3_info.channels == 2) {
|
||||
for(uint32_t i=0; i<dec_samples; i++)
|
||||
send_data[i] = s->dec_buf[2*i];
|
||||
}
|
||||
else {
|
||||
for(uint32_t i=0; i<dec_samples; i++)
|
||||
send_data[i] = s->dec_buf[i];
|
||||
}
|
||||
enc_ptr_offset += mp3_info.frame_bytes;
|
||||
unproc_data_size -= mp3_info.frame_bytes;
|
||||
send_frame_buf->len = dec_samples*2;
|
||||
send_frame_buf->mtype = F_AUDIO;
|
||||
send_frame_buf->stype = FSTYPE_AUDIO_PCM;
|
||||
s->audio_track.samplerate = mp3_info.samplerate;
|
||||
if(s->use_tpc && !s->autpc_msi) {
|
||||
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
|
||||
if(s->autpc_msi == NULL) {
|
||||
goto mp3_decode_end;
|
||||
}
|
||||
if(s->direct_to_dac) {
|
||||
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_add_output(s->msi, NULL, s->autpc_msi->name);
|
||||
}
|
||||
ret = msi_output_fb(s->msi, send_frame_buf);
|
||||
MP3_DEBUG("mp3 decode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
if(endOfRead)
|
||||
goto mp3_decode_end;
|
||||
}
|
||||
mp3_decode_end:
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
if(recv_frame_buf) {
|
||||
msi_delete_fb(NULL, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
}
|
||||
if(send_frame_buf) {
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
if(mp3_dec) {
|
||||
audio_coder_close(mp3_dec);
|
||||
}
|
||||
}
|
||||
|
||||
static void mp3_decode_thread(void *d)
|
||||
{
|
||||
struct mp3_decode_struct *s = (struct mp3_decode_struct *)d;
|
||||
|
||||
if(s->mp3_fp) {
|
||||
curmp3_info_init(&s->cur_mp3_info, s->mp3_filename);
|
||||
s->file_size = osal_fsize(s->mp3_fp);
|
||||
get_curmp3_size(s->cur_mp3_info, s->file_size);
|
||||
find_first_frame(s->cur_mp3_info, s->mp3_fp);
|
||||
if(s->cur_mp3_info->normal_frame_offset)
|
||||
s->get_first_frame = 1;
|
||||
}
|
||||
|
||||
msi_get(s->msi);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
s->msi->enable = 1;
|
||||
if(s->mp3_fp) {
|
||||
do {
|
||||
if(s->cur_mp3_info)
|
||||
osal_fseek(s->mp3_fp, s->cur_mp3_info->first_frame_offset);
|
||||
else
|
||||
osal_fseek(s->mp3_fp, 0);
|
||||
mp3_file_decode(s);
|
||||
if(s->current_status == AUCODEC_EXIT) {
|
||||
break;
|
||||
}
|
||||
}while(s->loop_mode);
|
||||
}
|
||||
else
|
||||
mp3_msi_decode(s);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
s->audio_track.priority = play_disabled;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
os_event_set(&s->event, coder_exit_event, NULL);
|
||||
|
||||
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
|
||||
s->current_status = AUCODEC_END;
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
if(s->cur_mp3_info)
|
||||
clear_curmp3_info(s->cur_mp3_info);
|
||||
|
||||
if(s->src_msi) {
|
||||
msi_del_output(s->src_msi, NULL, s->msi->name);
|
||||
s->src_msi = NULL;
|
||||
}
|
||||
|
||||
if(s->next_status != AUCODEC_EXIT)
|
||||
msi_destroy(s->msi);
|
||||
|
||||
msi_put(s->msi);
|
||||
}
|
||||
|
||||
static int32_t mp3_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct mp3_decode_struct *mp3_decode_s = (struct mp3_decode_struct*)(msi->priv);
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_AUCODER:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(mp3_decode_s) {
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUCODER_PAUSE:
|
||||
{
|
||||
if(mp3_decode_s->current_status == AUCODEC_RUN) {
|
||||
mp3_decode_s->next_status = AUCODEC_PAUSE;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CONTINUE:
|
||||
{
|
||||
if(mp3_decode_s->current_status == AUCODEC_PAUSE) {
|
||||
mp3_decode_s->next_status = AUCODEC_RUN;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_STATUS:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(mp3_decode_s->current_status);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SPEED:
|
||||
{
|
||||
mp3_decode_s->speed = (uint8_t)param2;
|
||||
ret = msi_output_cmd(mp3_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(mp3_decode_s->speed));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_SPEED:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(mp3_decode_s->speed);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_PITCH:
|
||||
{
|
||||
mp3_decode_s->pitch = (uint8_t)param2;
|
||||
ret = msi_output_cmd(mp3_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(mp3_decode_s->pitch));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_PITCH:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(mp3_decode_s->pitch);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CLEAR_STREAM:
|
||||
{
|
||||
os_event_set(&mp3_decode_s->event, coder_clear_event, NULL);
|
||||
os_event_wait(&mp3_decode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
msi_output_cmd(mp3_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(mp3_decode_s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_CLEAR_STREAM,(uint32_t)(&(mp3_decode_s->audio_track)));
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SRCMSI:
|
||||
{
|
||||
if(mp3_decode_s->src_msi) {
|
||||
msi_del_output(mp3_decode_s->src_msi, NULL, msi->name);
|
||||
}
|
||||
mp3_decode_s->src_msi = NULL;
|
||||
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
|
||||
if(ret == RET_OK) {
|
||||
mp3_decode_s->src_msi = (struct msi*)param2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DIRECT_TO_DAC:
|
||||
{
|
||||
uint32_t direct_to_dac = param2;
|
||||
if(direct_to_dac && mp3_decode_s->direct_to_dac == 0) {
|
||||
mp3_decode_s->direct_to_dac = 1;
|
||||
if(mp3_decode_s->use_tpc == 0) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(mp3_decode_s->autpc_msi) {
|
||||
msi_add_output(mp3_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(mp3_decode_s->audio_track)));
|
||||
}
|
||||
else if(mp3_decode_s->direct_to_dac == 1) {
|
||||
mp3_decode_s->direct_to_dac = 0;
|
||||
if(mp3_decode_s->use_tpc == 0) {
|
||||
msi_del_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(mp3_decode_s->autpc_msi) {
|
||||
msi_del_output(mp3_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
mp3_decode_s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(mp3_decode_s->audio_track)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DEINIT:
|
||||
{
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->mtype == F_AUDIO) {
|
||||
ret = RET_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(mp3_decode_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
fbpool_put(&mp3_decode_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if(mp3_decode_s && mp3_decode_s->task_hdl) {
|
||||
mp3_decode_s->next_status = AUCODEC_EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(mp3_decode_s) {
|
||||
if(mp3_decode_s->task_hdl) {
|
||||
os_event_wait(&mp3_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
}
|
||||
for(uint32_t i=0; i<MAX_MP3_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (mp3_decode_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
MP3_DECODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&mp3_decode_s->tx_pool);
|
||||
if(mp3_decode_s->event.hdl) {
|
||||
os_event_del(&mp3_decode_s->event);
|
||||
}
|
||||
if(mp3_decode_s->mp3_fp) {
|
||||
osal_fclose(mp3_decode_s->mp3_fp);
|
||||
mp3_decode_s->mp3_fp = NULL;
|
||||
}
|
||||
if(mp3_decode_s->autpc_msi) {
|
||||
autpc_msi_deinit(mp3_decode_s->autpc_msi);
|
||||
mp3_decode_s->autpc_msi = NULL;
|
||||
}
|
||||
if(mp3_decode_s->msi_name) {
|
||||
MP3_DECODE_FREE(mp3_decode_s->msi_name);
|
||||
mp3_decode_s->msi_name = NULL;
|
||||
}
|
||||
MP3_DECODE_FREE(mp3_decode_s);
|
||||
mp3_decode_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *mp3_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init)
|
||||
{
|
||||
#if AUDIO_EN
|
||||
char *msi_name = NULL;
|
||||
|
||||
msi_name = (char*)MP3_DECODE_ZALLOC(sizeof(char)*32);
|
||||
if(msi_name == NULL) {
|
||||
os_printf("alloc autpc msi namefail\n");
|
||||
return NULL;
|
||||
}
|
||||
os_snprintf(msi_name, 20, "SR_MP3_DECODE_""%04d", (int)(os_jiffies()));
|
||||
struct msi *msi = msi_new(msi_name, MAX_MP3_DECODE_RXBUF, NULL);
|
||||
os_printf("mp3 msi name:%s\n",msi_name);
|
||||
if(msi == NULL) {
|
||||
MP3_INFO("create mp3 decode msi fail!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
struct mp3_decode_struct *mp3_decode_s = (struct mp3_decode_struct*)MP3_DECODE_ZALLOC(sizeof(struct mp3_decode_struct));
|
||||
if(!mp3_decode_s) {
|
||||
MP3_INFO("mp3_decode_s malloc fail!\r\n");
|
||||
goto mp3_decode_init_err;
|
||||
}
|
||||
msi->priv = mp3_decode_s;
|
||||
msi->action = (msi_action)mp3_decode_msi_action;
|
||||
fbpool_init(&mp3_decode_s->tx_pool, MAX_MP3_DECODE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_MP3_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (mp3_decode_s->tx_pool.pool)+i;
|
||||
frame_buf->data = (uint8_t*)MP3_DECODE_MALLOC(1152 * sizeof(int16_t));
|
||||
if(frame_buf->data == NULL)
|
||||
{
|
||||
MP3_INFO("mp3 decode malloc framebuff data fail!\r\n");
|
||||
goto mp3_decode_init_err;
|
||||
}
|
||||
frame_buf->priv = &(mp3_decode_s->audio_track);
|
||||
}
|
||||
if(os_event_init(&mp3_decode_s->event) != RET_OK) {
|
||||
MP3_INFO("create mp3 decode event fail!\r\n");
|
||||
goto mp3_decode_init_err;
|
||||
}
|
||||
if(filename) {
|
||||
os_memcpy(mp3_decode_s->mp3_filename, filename, 20);
|
||||
mp3_decode_s->mp3_fp = osal_fopen((const char*)mp3_decode_s->mp3_filename, "rb");
|
||||
if(mp3_decode_s->mp3_fp == NULL) {
|
||||
MP3_INFO("open mp3 file %s fail!\r\n", mp3_decode_s->mp3_filename);
|
||||
goto mp3_decode_init_err;
|
||||
}
|
||||
}
|
||||
if(audec_init->src_msi && (msi_add_output(audec_init->src_msi, NULL, msi->name) != RET_OK)) {
|
||||
goto mp3_decode_init_err;
|
||||
}
|
||||
mp3_decode_s->msi = msi;
|
||||
mp3_decode_s->msi_name = msi_name;
|
||||
mp3_decode_s->src_msi = audec_init->src_msi;
|
||||
mp3_decode_s->loop_mode = loop_mode;
|
||||
mp3_decode_s->direct_to_dac = audec_init->direct_to_dac;
|
||||
mp3_decode_s->use_tpc = audec_init->use_tpc;
|
||||
mp3_decode_s->speed = audec_init->speed;
|
||||
mp3_decode_s->pitch = audec_init->pitch;
|
||||
mp3_decode_s->destroy_self = audec_init->destroy_self;
|
||||
mp3_decode_s->audio_track.priority = audec_init->priority;
|
||||
mp3_decode_s->audio_track.track_type = audec_init->track_type;
|
||||
mp3_decode_s->next_status = AUCODEC_RUN;
|
||||
mp3_decode_s->current_status = AUCODEC_RUN;
|
||||
if(audec_init->direct_to_dac && !mp3_decode_s->use_tpc) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
mp3_decode_s->task_hdl = os_task_create("mp3_decode_thread", mp3_decode_thread, (void*)mp3_decode_s, OS_TASK_PRIORITY_BELOW_NORMAL, 0, NULL, 3072);
|
||||
if(mp3_decode_s->task_hdl == NULL) {
|
||||
MP3_INFO("create mp3 decode task fail!\r\n");
|
||||
goto mp3_decode_init_err;
|
||||
}
|
||||
return msi;
|
||||
|
||||
mp3_decode_init_err:
|
||||
msi_destroy(msi);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
26
sdk/app/audio_media_ctrl/mp3/mp3_decode.h
Normal file
26
sdk/app/audio_media_ctrl/mp3/mp3_decode.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _MP3_DECODE_MSI_H_
|
||||
#define _MP3_DECODE_MSI_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "audio_code_ctrl.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define MP3_DECODE_MALLOC av_psram_malloc
|
||||
#define MP3_DECODE_ZALLOC av_psram_zalloc
|
||||
#define MP3_DECODE_CALLOC av_psram_calloc
|
||||
#define MP3_DECODE_FREE av_psram_free
|
||||
#else
|
||||
#define MP3_DECODE_MALLOC av_malloc
|
||||
#define MP3_DECODE_ZALLOC av_zalloc
|
||||
#define MP3_DECODE_CALLOC av_calloc
|
||||
#define MP3_DECODE_FREE av_free
|
||||
#endif
|
||||
|
||||
#define MP3_DEBUG(fmt, args...) //os_printf(fmt, ##args)
|
||||
#define MP3_INFO os_printf
|
||||
|
||||
struct msi *mp3_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init);
|
||||
|
||||
#endif
|
||||
472
sdk/app/audio_media_ctrl/mp3/mp3_getInfo.c
Normal file
472
sdk/app/audio_media_ctrl/mp3/mp3_getInfo.c
Normal file
@@ -0,0 +1,472 @@
|
||||
#include "basic_include.h"
|
||||
//#include "keyWork.h"
|
||||
//#include "keyScan.h"
|
||||
#include "osal_file.h"
|
||||
#include "mp3_getInfo.h"
|
||||
#include "mp3_decode.h"
|
||||
#include "audio_code_ctrl.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
|
||||
#define MP3_SAVE_INFO 0
|
||||
|
||||
#if MP3_SAVE_INFO
|
||||
#define MAX_FORWARD_TIME 10
|
||||
struct key_callback_list_s *key_seek_list = NULL;
|
||||
#endif
|
||||
|
||||
const uint32_t bitrate_table[5][15] = {
|
||||
/* MPEG-1 */
|
||||
{ 0, 32000, 64000, 96000, 128000, 160000, 192000, 224000, /* Layer I */
|
||||
256000, 288000, 320000, 352000, 384000, 416000, 448000 },
|
||||
{ 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer II */
|
||||
128000, 160000, 192000, 224000, 256000, 320000, 384000 },
|
||||
{ 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, /* Layer III */
|
||||
112000, 128000, 160000, 192000, 224000, 256000, 320000 },
|
||||
/* MPEG-2 ,MPEG-2.5 */
|
||||
{ 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer I */
|
||||
128000, 144000, 160000, 176000, 192000, 224000, 256000 },
|
||||
{ 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, /* Layer */
|
||||
64000, 80000, 96000, 112000, 128000, 144000, 160000 } /* II & III */
|
||||
};
|
||||
const uint32_t samplingrate_table[4][3] = { //value s are in Hz
|
||||
{11025 , 12000 , 8000}, //MPEG Version 2.5
|
||||
{0,0,0}, //reserved
|
||||
{22050, 24000, 16000}, //MPEG Version 2 (ISO/IEC 13818-3)
|
||||
{44100, 48000, 32000} //MPEG Version 1 (ISO/IEC 11172-3)
|
||||
};
|
||||
const uint8_t layerIII_inbytes[4][4] = {
|
||||
{17,17,17,9}, /*MPEG Version 2.5*/
|
||||
{0, 0, 0, 0}, /*reserved*/
|
||||
{17,17,17,9}, /*MPEG Version 2*/
|
||||
{32,32,32,17} /*MPEG Version 1*/
|
||||
};
|
||||
const uint16_t samples_table[4][4] = {
|
||||
{0,576,1152,384}, /*MPEG Version 2.5 {reserve,layerIII,layerII,layerI}*/
|
||||
{0,0,0,0}, /*reserved {reserve,layerIII,layerII,layerI}*/
|
||||
{0,576,1152,384}, /*MPEG Version 2 {reserve,layerIII,layerII,layerI}*/
|
||||
{0,1152,1152,384} /*MPEG Version 1 {reserve,layerIII,layerII,layerI}*/
|
||||
};
|
||||
|
||||
uint32_t get_curmp3_size(CUR_MP3_INFO *cur_mp3_info, uint32_t s)
|
||||
{
|
||||
if(!cur_mp3_info)
|
||||
return 0;
|
||||
cur_mp3_info->total_size =s;
|
||||
return cur_mp3_info->total_size;
|
||||
}
|
||||
|
||||
void curmp3_info_init(CUR_MP3_INFO **cur_mp3_info, uint8_t *mp3_filename)
|
||||
{
|
||||
#if MP3_SAVE_INFO
|
||||
char dirname_len = strlen("0:mp3/");
|
||||
char extension_len = strlen("mp3");
|
||||
char filename_temp[50] = {0};
|
||||
#endif
|
||||
if(!(*cur_mp3_info))
|
||||
(*cur_mp3_info) = (CUR_MP3_INFO*)MP3_DECODE_ZALLOC(sizeof(CUR_MP3_INFO));
|
||||
else
|
||||
os_memset((*cur_mp3_info), 0, sizeof(CUR_MP3_INFO));
|
||||
#if MP3_SAVE_INFO
|
||||
os_memcpy(filename_temp, mp3_filename+dirname_len, strlen(mp3_filename)-dirname_len-extension_len);
|
||||
filename_temp[strlen(mp3_filename)-dirname_len-extension_len] = '\0';
|
||||
os_sprintf((*cur_mp3_info)->mp3_st_filename, "0:MP3_SEEK/%s%s", filename_temp, "st");
|
||||
os_printf("mp3_st_filename:%s\n",(*cur_mp3_info)->mp3_st_filename);
|
||||
#endif
|
||||
}
|
||||
|
||||
// void get_curmp3_totaltime_ergodic(void *fp, uint32_t first_frame_offset)
|
||||
// {
|
||||
|
||||
// uint8_t bitrate_index = 0;
|
||||
// uint8_t padding = 0;
|
||||
// uint8_t frame_head[4];
|
||||
// int32_t read_len = 0;
|
||||
// uint32_t bitrate = 0;
|
||||
// uint32_t frame_len = 0;
|
||||
// uint32_t offset = 0;
|
||||
// uint32_t current_seek = 0;
|
||||
// uint32_t read_frame_cnt = 0;
|
||||
// uint32_t read_second_cnt = 0;
|
||||
|
||||
// if(!cur_mp3_info)
|
||||
// return;
|
||||
|
||||
// current_seek = osal_ftell(fp);
|
||||
// osal_fseek(fp, first_frame_offset);
|
||||
// osal_fread(frame_head, 1, 4, fp);
|
||||
// offset = first_frame_offset;
|
||||
|
||||
// bitrate_index = (frame_head[2]>>4)&0xf;
|
||||
// bitrate = bitrate_table[cur_mp3_info->bitrate_table_index][bitrate_index];
|
||||
// padding = ((frame_head[2]>>1)&0x1) * cur_mp3_info->padding_mul;
|
||||
// frame_len = cur_mp3_info->samples/8*bitrate/cur_mp3_info->samplingrate + padding;
|
||||
|
||||
// offset = first_frame_offset+4;
|
||||
// // printf("samples:%d samplingrate:%d bitrate:%d\n",cur_mp3_info->samples,cur_mp3_info->samplingrate,bitrate);
|
||||
// INIT_LIST_HEAD((struct list_head *)&cur_mp3_info->seek_table_head);
|
||||
// MP3_SEEK_TABLE *sub_seek_table = MP3_DECODE_ZALLOC(sizeof(MP3_SEEK_TABLE));
|
||||
// list_add_tail((struct list_head *)&sub_seek_table->sub_table_list,(struct list_head *)&cur_mp3_info->seek_table_head);
|
||||
// sub_seek_table->sub_table[0] = first_frame_offset;
|
||||
// while(1) {
|
||||
// osal_fseek(fp, offset+frame_len-4);
|
||||
// offset += frame_len;
|
||||
// read_len = osal_fread(frame_head, 1, 4, fp);
|
||||
// if(((cur_mp3_info->total_size-offset)==124) && (strncmp((const char*)frame_head, "TAG", 3)==0)) { //ID3V1
|
||||
// break;
|
||||
// }
|
||||
// if(((frame_head[0]<<8) | (frame_head[1]&0xE0)) != 0xFFE0) {
|
||||
// break;
|
||||
// }
|
||||
// if((offset+frame_len-4) >= cur_mp3_info->total_size ) { //end
|
||||
// break;
|
||||
// }
|
||||
// cur_mp3_info->total_frame++;
|
||||
// bitrate_index = (frame_head[2]>>4)&0xf;
|
||||
// bitrate = bitrate_table[cur_mp3_info->bitrate_table_index][bitrate_index];
|
||||
// padding = ((frame_head[2]>>1)&0x1) * cur_mp3_info->padding_mul;
|
||||
// frame_len = cur_mp3_info->samples/8*bitrate/cur_mp3_info->samplingrate + padding;
|
||||
// read_frame_cnt++;
|
||||
// if(read_frame_cnt >= (cur_mp3_info->one_second_frame)) {
|
||||
// read_second_cnt++;
|
||||
// if(read_second_cnt >= 100) {
|
||||
// sub_seek_table = (MP3_SEEK_TABLE*)MP3_DECODE_ZALLOC(sizeof(MP3_SEEK_TABLE));
|
||||
// list_add_tail((struct list_head *)&sub_seek_table->sub_table_list,(struct list_head *)&cur_mp3_info->seek_table_head);
|
||||
// read_second_cnt -= 100;
|
||||
// }
|
||||
// sub_seek_table->sub_table[read_second_cnt] = offset-4;
|
||||
// read_frame_cnt -= (cur_mp3_info->one_second_frame);
|
||||
// }
|
||||
// }
|
||||
// cur_mp3_info->totaltime = cur_mp3_info->total_frame * cur_mp3_info->samples / cur_mp3_info->samplingrate;
|
||||
// cur_mp3_info->once_move_time = (cur_mp3_info->totaltime%100)?(cur_mp3_info->totaltime/100+1):(cur_mp3_info->totaltime/100);
|
||||
// MP3_INFO("total_frame:%d total_time:%d once_move_time:%d\n",cur_mp3_info->total_frame, cur_mp3_info->totaltime,cur_mp3_info->once_move_time);
|
||||
// cur_mp3_info->get_totaltime = 1;
|
||||
// osal_fseek(fp, current_seek);
|
||||
// }
|
||||
|
||||
// uint32_t get_mp3_seek(void)
|
||||
// {
|
||||
// if(!cur_mp3_info)
|
||||
// return 0;
|
||||
|
||||
// return cur_mp3_info->offset_seek;
|
||||
// }
|
||||
|
||||
// uint32_t get_curmp3_playtime(void)
|
||||
// {
|
||||
// if(!cur_mp3_info)
|
||||
// return 0;
|
||||
|
||||
// cur_mp3_info->playtime = cur_mp3_info->play_frame * cur_mp3_info->samples / cur_mp3_info->samplingrate;
|
||||
// // printf("record:%d %d\n",cur_mp3_info->playtime,cur_mp3_info->play_frame);
|
||||
// return cur_mp3_info->playtime;
|
||||
// }
|
||||
// uint32_t get_curmp3_playframe(void)
|
||||
// {
|
||||
// if(!cur_mp3_info)
|
||||
// return 0;
|
||||
|
||||
// cur_mp3_info->play_frame++;
|
||||
// return cur_mp3_info->play_frame;
|
||||
// }
|
||||
// void update_curmp3_playtime(uint32_t update_time)
|
||||
// {
|
||||
// if(!cur_mp3_info)
|
||||
// return;
|
||||
|
||||
// cur_mp3_info->playtime = update_time;
|
||||
// }
|
||||
// void update_curmp3_playframe(uint32_t update_frame)
|
||||
// {
|
||||
// if(!cur_mp3_info)
|
||||
// return;
|
||||
|
||||
// cur_mp3_info->play_frame = update_frame;
|
||||
// }
|
||||
|
||||
// void set_mp3_seek(int16_t move_time)
|
||||
// {
|
||||
// uint8_t table_pos = 0;
|
||||
// uint32_t offset_seek = 0;
|
||||
// uint32_t target_time = 0;
|
||||
// uint32_t target_frame = 0;
|
||||
// uint32_t table_index = 0;
|
||||
// struct list_head *seek_table_list = NULL;
|
||||
// MP3_SEEK_TABLE *seek_table = NULL;
|
||||
|
||||
// target_time = ((cur_mp3_info->playtime + move_time)<0)?0:(cur_mp3_info->playtime + move_time);
|
||||
// target_time = (target_time>cur_mp3_info->totaltime)?cur_mp3_info->totaltime:target_time;
|
||||
// target_frame = cur_mp3_info->one_second_frame*target_time;
|
||||
// table_index = target_time/100;
|
||||
// table_pos = target_time%100;
|
||||
// seek_table_list = cur_mp3_info->seek_table_head.next;
|
||||
// while(table_index>0) {
|
||||
// seek_table_list = seek_table_list->next;
|
||||
// table_index--;
|
||||
// }
|
||||
// seek_table = list_entry((struct list_head *)seek_table_list,MP3_SEEK_TABLE,sub_table_list);
|
||||
// offset_seek = seek_table->sub_table[table_pos];
|
||||
// osal_fseek(cur_mp3_info->mp3_fp,offset_seek);
|
||||
// update_curmp3_playtime(target_time);
|
||||
// update_curmp3_playframe(target_frame);
|
||||
// cur_mp3_info->offset_seek = offset_seek;
|
||||
// MP3_INFO("**file pos:%x time:%d frame:%d**\n",offset_seek,cur_mp3_info->playtime,cur_mp3_info->play_frame);
|
||||
// }
|
||||
// //
|
||||
// //uint32_t key_seek_callback(struct key_callback_list_s *callback_list,uint32_t keyvalue,uint32_t extern_value)
|
||||
// //{
|
||||
// // uint32 key_val = 0;
|
||||
// //
|
||||
// // if(!cur_mp3_info)
|
||||
// // return 0;
|
||||
// //
|
||||
// // if(((keyvalue>>8) != AD_A) && ((keyvalue>>8) != AD_B))
|
||||
// // return 0;
|
||||
// // if(get_mp3_decode_status() == MP3_STOP) {
|
||||
// // _os_printf("mp3 stop\n");
|
||||
// // return 0;
|
||||
// // }
|
||||
// // key_val = (keyvalue & 0xff);
|
||||
// // if((keyvalue>>8) == AD_A) {
|
||||
// // if(key_val == KEY_EVENT_DOWN) {
|
||||
// // os_sema_down(&seek_sema,5000);
|
||||
// // set_mp3_seek(-cur_mp3_info->once_move_time);
|
||||
// // }
|
||||
// // else if((key_val == KEY_EVENT_LDOWN) || (key_val == KEY_EVENT_REPEAT)) {
|
||||
// // set_mp3_seek(-cur_mp3_info->once_move_time);
|
||||
// // }
|
||||
// // else if((key_val == KEY_EVENT_SUP) || (key_val == KEY_EVENT_LUP)) {
|
||||
// // cur_mp3_info->update_fops = 1;
|
||||
// // os_sema_up(&seek_sema);
|
||||
// // }
|
||||
// // }
|
||||
// // else if((keyvalue>>8) == AD_B) {
|
||||
// // if(key_val == KEY_EVENT_DOWN) {
|
||||
// // os_sema_down(&seek_sema,5000);
|
||||
// // set_mp3_seek(cur_mp3_info->once_move_time);
|
||||
// // }
|
||||
// // else if((key_val == KEY_EVENT_LDOWN) || (key_val == KEY_EVENT_REPEAT)) {
|
||||
// // set_mp3_seek(cur_mp3_info->once_move_time);
|
||||
// // }
|
||||
// // else if((key_val == KEY_EVENT_SUP) || (key_val == KEY_EVENT_LUP)) {
|
||||
// // cur_mp3_info->update_fops = 1;
|
||||
// // os_sema_up(&seek_sema);
|
||||
// // }
|
||||
// // }
|
||||
// // return 1;
|
||||
// //}
|
||||
|
||||
// int32_t at_set_mp3_seek(const char *cmd, char *argv[], uint32_t argc)
|
||||
// {
|
||||
// int32_t seek_time = 0;
|
||||
// uint32_t forward_time = 0;
|
||||
|
||||
// if(!cur_mp3_info)
|
||||
// return 0;
|
||||
// // if(get_mp3_decode_status() == AUCODEC_EXIT) {
|
||||
// // MP3_INFO("mp3 stop\n");
|
||||
// // return 0;
|
||||
// // }
|
||||
// if(argc < 1) {
|
||||
// MP3_INFO("%s %d,enter the seek\n",__FUNCTION__,argc);
|
||||
// return 0;
|
||||
// }
|
||||
// if(argv[0]) {
|
||||
// seek_time = os_atoi(argv[0]);
|
||||
// if(seek_time == 0)
|
||||
// return 1;
|
||||
// // forward_time = (seek_time<MAX_FORWARD_TIME)?seek_time:MAX_FORWARD_TIME;
|
||||
// forward_time = seek_time;
|
||||
// os_sema_down(&seek_sema,5000);
|
||||
// set_mp3_seek(forward_time);
|
||||
// cur_mp3_info->update_fops = 1;
|
||||
// os_sema_up(&seek_sema);
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// int seektable_check(CUR_MP3_INFO *mp3_info)
|
||||
// {
|
||||
// int32_t ret = 0;
|
||||
// uint32_t read_buf[4] = {0};
|
||||
// uint32_t seek_table_len = 0;
|
||||
// uint32_t *cache_buf = NULL;
|
||||
|
||||
// cache_buf = (uint32_t*)MP3_DECODE_ZALLOC(sizeof(uint32_t)*100);
|
||||
// if(!cache_buf)
|
||||
// goto seektable_check_end;
|
||||
// osal_fread(read_buf, 4, 4, mp3_info->mp3_st_fp);
|
||||
// if((read_buf[0]==mp3_info->total_size) && (read_buf[1]==mp3_info->first_frame_offset)
|
||||
// && (read_buf[2]==mp3_info->normal_frame_offset)) {
|
||||
// mp3_info->total_frame = read_buf[3];
|
||||
// seek_table_len = osal_fsize(mp3_info->mp3_st_fp) - sizeof(read_buf);
|
||||
// INIT_LIST_HEAD((struct list_head *)&mp3_info->seek_table_head);
|
||||
// while(seek_table_len) {
|
||||
// MP3_SEEK_TABLE *sub_seek_table = MP3_DECODE_ZALLOC(sizeof(MP3_SEEK_TABLE));
|
||||
// list_add_tail((struct list_head *)&sub_seek_table->sub_table_list,(struct list_head *)&mp3_info->seek_table_head);
|
||||
// osal_fread((void*)cache_buf, 4, 100, mp3_info->mp3_st_fp);
|
||||
// os_memcpy(sub_seek_table->sub_table, cache_buf, sizeof(uint32_t)*100);
|
||||
// seek_table_len -= 100*4;
|
||||
// }
|
||||
// cur_mp3_info->totaltime = cur_mp3_info->total_frame * cur_mp3_info->samples / cur_mp3_info->samplingrate;
|
||||
// cur_mp3_info->once_move_time = (cur_mp3_info->totaltime%100)?(cur_mp3_info->totaltime/100+1):(cur_mp3_info->totaltime/100);
|
||||
// MP3_INFO("total_frame:%d total_time:%d once_move_time:%d\n",cur_mp3_info->total_frame, cur_mp3_info->totaltime,cur_mp3_info->once_move_time);
|
||||
// cur_mp3_info->get_totaltime = 1;
|
||||
// ret = 1;
|
||||
// }
|
||||
// seektable_check_end:
|
||||
// if(cache_buf)
|
||||
// MP3_DECODE_FREE((void*)cache_buf);
|
||||
// osal_fclose(mp3_info->mp3_st_fp);
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
void find_first_frame(CUR_MP3_INFO *cur_mp3_info, void *fp)
|
||||
{
|
||||
uint8_t mp3_head[512];
|
||||
uint8_t bitrate_index = 0;
|
||||
uint8_t channel_mode = 0x11;
|
||||
uint8_t padding = 0;
|
||||
uint8_t layer_index = 0;
|
||||
uint8_t mpeg_index = 0;
|
||||
uint8_t samplingrate_index = 0;
|
||||
int32_t bitrate = 0;
|
||||
uint32_t offset = 0;
|
||||
uint32_t first_frame_offset = 0;
|
||||
uint32_t seek = 0;
|
||||
uint32_t frame_len = 0;
|
||||
|
||||
if(!cur_mp3_info) {
|
||||
return;
|
||||
}
|
||||
osal_fread(mp3_head, 512, 1, fp);
|
||||
if(os_strncmp(mp3_head+offset, "ID3", 3) == 0) {
|
||||
uint32_t ID3V2_len = (mp3_head[6]&0x7F)*0x200000+ (mp3_head[7]&0x7F)*0x4000 +
|
||||
(mp3_head[8]&0x7F)*0x80 +(mp3_head[9]&0x7F);
|
||||
offset += (ID3V2_len+10);
|
||||
}
|
||||
MP3_INFO("ID3 offset:%x\n",offset);
|
||||
osal_fseek(fp,offset);
|
||||
seek = offset;
|
||||
osal_fread(mp3_head,1,512,fp);
|
||||
while(((mp3_head[offset-seek]<<8) | (mp3_head[offset-seek+1]&0xE0)) != 0xFFE0) {
|
||||
offset++;
|
||||
if((offset+1) > (seek+512)) {
|
||||
osal_fseek(fp,offset);
|
||||
osal_fread(mp3_head, 1, 512, fp);
|
||||
seek = offset;
|
||||
}
|
||||
}
|
||||
osal_fseek(fp,offset);
|
||||
seek = offset;
|
||||
osal_fread(mp3_head,1,512,fp);
|
||||
cur_mp3_info->mp3_fp = fp;
|
||||
first_frame_offset = offset;
|
||||
// os_printf("\n***first frame offset:%x****\n",first_frame_offset);
|
||||
cur_mp3_info->first_frame_offset = first_frame_offset;
|
||||
layer_index = (mp3_head[first_frame_offset-seek+1]>>1)&0x3;
|
||||
mpeg_index = (mp3_head[first_frame_offset-seek+1]>>3)&0x3;
|
||||
samplingrate_index = (mp3_head[first_frame_offset-seek+2]>>2)&0x3;
|
||||
cur_mp3_info->samplingrate = samplingrate_table[mpeg_index][samplingrate_index];
|
||||
cur_mp3_info->samples = samples_table[mpeg_index][layer_index];
|
||||
channel_mode = (mp3_head[first_frame_offset-seek+3]>>6)&0x3;
|
||||
if(mpeg_index == 3) { /*MPEG 1*/
|
||||
switch(layer_index) {
|
||||
case 0:break;
|
||||
case 1:cur_mp3_info->bitrate_table_index = 2;break; /*layer III*/
|
||||
case 2:cur_mp3_info->bitrate_table_index = 1;break; /*layer II*/
|
||||
case 3:cur_mp3_info->bitrate_table_index = 0;break; /*layer I*/
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
else if((mpeg_index == 0) || (mpeg_index == 2)) { /*MPEG 2、MPEG2.5*/
|
||||
switch(layer_index) {
|
||||
case 0:break;
|
||||
case 1:cur_mp3_info->bitrate_table_index = 4;break;
|
||||
case 2:cur_mp3_info->bitrate_table_index = 4;break;
|
||||
case 3:cur_mp3_info->bitrate_table_index = 3;break;
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
bitrate_index = (mp3_head[first_frame_offset-seek+2]>>4)&0xf;
|
||||
bitrate = bitrate_table[cur_mp3_info->bitrate_table_index][bitrate_index];
|
||||
if(layer_index == 3)
|
||||
cur_mp3_info->padding_mul = 4;
|
||||
else if((layer_index == 1) || (layer_index == 2))
|
||||
cur_mp3_info->padding_mul = 1;
|
||||
padding = ((mp3_head[first_frame_offset-seek+2]>>1)&0x1) * cur_mp3_info->padding_mul;
|
||||
frame_len = cur_mp3_info->samples/8*bitrate/cur_mp3_info->samplingrate + padding;
|
||||
MP3_INFO("first frame samples:%d samplingrate:%d channel_mode:%d bitrate:%d frame_len:%d\n",
|
||||
cur_mp3_info->samples,cur_mp3_info->samplingrate,channel_mode,bitrate,frame_len);
|
||||
cur_mp3_info->normal_frame_offset = cur_mp3_info->first_frame_offset+frame_len;
|
||||
cur_mp3_info->one_second_frame = cur_mp3_info->samplingrate/cur_mp3_info->samples;
|
||||
|
||||
#if MP3_SAVE_INFO
|
||||
int32_t ret = 0;
|
||||
DIR st_dir;
|
||||
os_sema_init(&seek_sema, 1);
|
||||
if(!key_seek_list)
|
||||
key_seek_list = add_keycallback(key_seek_callback, NULL);
|
||||
MP3_INFO("one_second_frame:%d",cur_mp3_info->one_second_frame);
|
||||
ret = f_opendir(&st_dir,"0:/MP3_SEEK");
|
||||
if(ret == FR_OK) {
|
||||
cur_mp3_info->mp3_st_fp = osal_fopen(cur_mp3_info->mp3_st_filename, "r");
|
||||
if(cur_mp3_info->mp3_st_fp) {
|
||||
if(seektable_check(cur_mp3_info)) {
|
||||
return;
|
||||
}
|
||||
osal_fclose(cur_mp3_info->mp3_st_fp);
|
||||
}
|
||||
}
|
||||
else{
|
||||
ret = f_mkdir("0:/MP3_SEEK");
|
||||
}
|
||||
get_curmp3_totaltime_ergodic(fp, first_frame_offset);
|
||||
cur_mp3_info->mp3_st_fp = osal_fopen(cur_mp3_info->mp3_st_filename, "wb");
|
||||
if(cur_mp3_info->mp3_st_fp) {
|
||||
osal_fwrite(cur_mp3_info, 4, 4, cur_mp3_info->mp3_st_fp);
|
||||
struct list_head *seek_table_list = cur_mp3_info->seek_table_head.next;
|
||||
struct list_head *seek_table_head = &cur_mp3_info->seek_table_head;
|
||||
while(seek_table_list != seek_table_head) {
|
||||
MP3_SEEK_TABLE *seek_table = list_entry((struct list_head *)seek_table_list,MP3_SEEK_TABLE,sub_table_list);
|
||||
osal_fwrite(seek_table->sub_table, 100, 4, cur_mp3_info->mp3_st_fp);
|
||||
seek_table_list = seek_table_list->next;
|
||||
}
|
||||
osal_fclose(cur_mp3_info->mp3_st_fp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// uint32_t get_curmp3_songtime(uint32_t brate)
|
||||
// {
|
||||
// if(!cur_mp3_info) {
|
||||
// return 0;
|
||||
// }
|
||||
// if(cur_mp3_info->get_totaltime == 1) {
|
||||
// return cur_mp3_info->totaltime;
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
void clear_curmp3_info(CUR_MP3_INFO *cur_mp3_info)
|
||||
{
|
||||
if(cur_mp3_info) {
|
||||
MP3_DECODE_FREE(cur_mp3_info);
|
||||
}
|
||||
#if MP3_SAVE_INFO
|
||||
if(key_seek_list) {
|
||||
remove_keycallback(key_seek_list);
|
||||
key_seek_list = NULL;
|
||||
}
|
||||
struct list_head *list_n = (struct list_head *)&cur_mp3_info->seek_table_head;
|
||||
struct list_head *head = (struct list_head *)&cur_mp3_info->seek_table_head;
|
||||
MP3_SEEK_TABLE *seek_table = NULL;
|
||||
while(list_n->next != head) {
|
||||
list_n = list_n->next;
|
||||
seek_table = list_entry((struct list_head *)list_n,MP3_SEEK_TABLE,sub_table_list);
|
||||
MP3_DECODE_FREE(seek_table);
|
||||
}
|
||||
os_sema_del(&seek_sema);
|
||||
#endif
|
||||
}
|
||||
46
sdk/app/audio_media_ctrl/mp3/mp3_getInfo.h
Normal file
46
sdk/app/audio_media_ctrl/mp3/mp3_getInfo.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef _MP3_GETINFO_MSI_H_
|
||||
#define _MP3_GETINFO_MSI_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
|
||||
typedef struct {
|
||||
struct list_head sub_table_list;
|
||||
uint32_t sub_table[100];
|
||||
}MP3_SEEK_TABLE;
|
||||
|
||||
typedef struct {
|
||||
uint32_t total_size;
|
||||
uint32_t first_frame_offset;
|
||||
uint32_t normal_frame_offset;
|
||||
uint32_t total_frame;
|
||||
uint32_t once_move_time;
|
||||
uint32_t offset_seek;
|
||||
uint32_t samplingrate;
|
||||
uint32_t one_second_frame;
|
||||
int32_t playtime;
|
||||
int32_t play_frame;
|
||||
|
||||
uint16_t totaltime;
|
||||
uint16_t samples;
|
||||
|
||||
uint8_t get_totaltime;
|
||||
uint8_t update_fops;
|
||||
|
||||
uint8_t bitrate_table_index;
|
||||
uint8_t padding_mul;
|
||||
|
||||
void *mp3_fp;
|
||||
void *mp3_st_fp;
|
||||
char mp3_st_filename[50];
|
||||
|
||||
struct list_head seek_table_head;
|
||||
}CUR_MP3_INFO;
|
||||
|
||||
struct os_semaphore seek_sema;
|
||||
|
||||
uint32_t get_curmp3_size(CUR_MP3_INFO *cur_mp3_info, uint32_t s);
|
||||
void curmp3_info_init(CUR_MP3_INFO **cur_mp3_info, uint8_t *mp3_filename);
|
||||
void clear_curmp3_info(CUR_MP3_INFO *cur_mp3_info);
|
||||
void find_first_frame(CUR_MP3_INFO *cur_mp3_info, void *fp);
|
||||
|
||||
#endif
|
||||
27
sdk/app/audio_media_ctrl/opus/opus_code.h
Normal file
27
sdk/app/audio_media_ctrl/opus/opus_code.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef _OPUS_CODE_H_
|
||||
#define _OPUS_CODE_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "audio_code_ctrl.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define OPUS_CODE_MALLOC av_psram_malloc
|
||||
#define OPUS_CODE_ZALLOC av_psram_zalloc
|
||||
#define OPUS_CODE_CALLOC av_psram_calloc
|
||||
#define OPUS_CODE_FREE av_psram_free
|
||||
#else
|
||||
#define OPUS_CODE_MALLOC av_malloc
|
||||
#define OPUS_CODE_ZALLOC av_zalloc
|
||||
#define OPUS_CODE_CALLOC av_calloc
|
||||
#define OPUS_CODE_FREE av_free
|
||||
#endif
|
||||
|
||||
#define OPUS_DEBUG(fmt, args...) //os_printf(fmt, ##args)
|
||||
#define OPUS_INFO os_printf
|
||||
|
||||
struct msi *opus_encode_init(uint32_t samplerate, AUENC_INIT *auenc_init);
|
||||
struct msi *opus_decode_init(uint32_t samplerate, AUDEC_INIT *audec_init);
|
||||
|
||||
#endif
|
||||
454
sdk/app/audio_media_ctrl/opus/opus_decode.c
Normal file
454
sdk/app/audio_media_ctrl/opus/opus_decode.c
Normal file
@@ -0,0 +1,454 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/audio/audio_code/audio_code.h"
|
||||
#include "autpc_msi/autpc_msi.h"
|
||||
#include "opus_code.h"
|
||||
|
||||
#define MAX_OPUS_DECODE_RXBUF 4
|
||||
#define MAX_OPUS_DECODE_TXBUF 4
|
||||
|
||||
struct opus_decode_struct {
|
||||
AUDIO_TRACK audio_track;
|
||||
struct fbpool tx_pool;
|
||||
struct os_event event;
|
||||
struct msi *msi;
|
||||
struct msi *src_msi;
|
||||
struct msi *autpc_msi;
|
||||
char *msi_name;
|
||||
void *task_hdl;
|
||||
uint8_t direct_to_dac;
|
||||
uint8_t use_tpc;
|
||||
uint8_t speed;
|
||||
uint8_t pitch;
|
||||
uint8_t destroy_self;
|
||||
uint8_t next_status;
|
||||
uint8_t current_status;
|
||||
int16_t dec_buf[960]; //按照16k、60ms的最大长度,若超过该长度则需修改数组大小;
|
||||
uint32_t coder_sampleRate;
|
||||
};
|
||||
|
||||
static void opus_decode(struct opus_decode_struct *s)
|
||||
{
|
||||
uint8_t clear_finish = 1;
|
||||
uint8_t *enc_ptr = NULL;
|
||||
int32_t ret = 0;
|
||||
int32_t data_len = 0;
|
||||
int32_t dec_samples = 0;
|
||||
uint32_t dec_operation = 0;
|
||||
uint32_t clear_flag = 0;
|
||||
struct framebuff *recv_frame_buf = NULL;
|
||||
struct framebuff *send_frame_buf = NULL;
|
||||
AUCODE_HDL *opus_dec = NULL;
|
||||
AUCODE_FRAME_INFO opus_info;
|
||||
|
||||
opus_dec = audio_coder_open(OPUS_DEC, s->coder_sampleRate, 1);
|
||||
if(!opus_dec)
|
||||
return;
|
||||
while(1) {
|
||||
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
|
||||
if(clear_flag & coder_clear_event) {
|
||||
clear_flag = 0;
|
||||
clear_finish = 0;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
audio_coder_close(opus_dec);
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
opus_dec = audio_coder_open(OPUS_DEC, s->coder_sampleRate, 1);
|
||||
if(!opus_dec)
|
||||
return;
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
}
|
||||
recv_frame_buf = msi_get_fb(s->msi, 0);
|
||||
if(recv_frame_buf) {
|
||||
if(clear_finish == 0) {
|
||||
goto opus_decode_frame_end;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
goto opus_decode_frame_end;
|
||||
}
|
||||
else {
|
||||
s->current_status = AUCODEC_RUN;
|
||||
while(!send_frame_buf) {
|
||||
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(!send_frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
if(recv_frame_buf->priv)
|
||||
dec_operation = ((AUDECODER_OPERATION*)recv_frame_buf->priv)->decode_operation;
|
||||
if(dec_operation == PACKET_LOSS_CONCEALMENT)
|
||||
dec_samples = audio_decode_do_plc(opus_dec, s->dec_buf);
|
||||
else if(dec_operation == OUTPUT_MUTE_DATA)
|
||||
dec_samples = audio_decode_output_mute(opus_dec, s->dec_buf);
|
||||
else {
|
||||
if(dec_operation == DECODE_ADD_FADE_IN)
|
||||
audio_decode_fade_in(opus_dec);
|
||||
else if(dec_operation == DECODE_ADD_FADE_OUT)
|
||||
audio_decode_fade_out(opus_dec);
|
||||
data_len = recv_frame_buf->len;
|
||||
if(data_len > 0) {
|
||||
enc_ptr = recv_frame_buf->data;
|
||||
dec_samples = audio_decode_data(opus_dec, enc_ptr, data_len, s->dec_buf, &opus_info);
|
||||
}
|
||||
else {
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
goto opus_decode_frame_end;
|
||||
}
|
||||
}
|
||||
if(dec_samples <= 0) {
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
goto opus_decode_frame_end;
|
||||
}
|
||||
send_frame_buf->data = (uint8_t*)OPUS_CODE_MALLOC(dec_samples*2);
|
||||
if(!send_frame_buf->data) {
|
||||
OPUS_INFO("opus decode malloc send_frame_buf->data fail!\n");
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
goto opus_decode_frame_end;
|
||||
}
|
||||
os_memcpy(send_frame_buf->data, s->dec_buf, dec_samples*2);
|
||||
send_frame_buf->len = dec_samples*2;
|
||||
send_frame_buf->mtype = F_AUDIO;
|
||||
send_frame_buf->stype = FSTYPE_AUDIO_PCM;
|
||||
s->audio_track.samplerate = opus_info.samplerate;
|
||||
if(s->use_tpc && !s->autpc_msi) {
|
||||
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, dec_samples, &(s->audio_track));
|
||||
if(s->autpc_msi == NULL) {
|
||||
goto opus_decode_end;
|
||||
}
|
||||
if(s->direct_to_dac) {
|
||||
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_add_output(s->msi, NULL, s->autpc_msi->name);
|
||||
}
|
||||
ret = msi_output_fb(s->msi, send_frame_buf);
|
||||
OPUS_DEBUG("opus decode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
opus_decode_frame_end:
|
||||
OPUS_DEBUG("opus decode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
|
||||
msi_delete_fb(s->msi, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
}
|
||||
else {
|
||||
if(clear_finish == 0) {
|
||||
clear_finish = 1;
|
||||
os_event_set(&s->event, coder_clear_finish_event, NULL);
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
goto opus_decode_end;
|
||||
}
|
||||
}
|
||||
opus_decode_end:
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
if(recv_frame_buf) {
|
||||
msi_delete_fb(NULL, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
}
|
||||
if(send_frame_buf) {
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
if(opus_dec)
|
||||
audio_coder_close(opus_dec);
|
||||
}
|
||||
|
||||
static void opus_decode_thread(void *d)
|
||||
{
|
||||
struct opus_decode_struct *s = (struct opus_decode_struct *)d;
|
||||
|
||||
msi_get(s->msi);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
s->msi->enable = 1;
|
||||
opus_decode(s);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
os_event_set(&s->event, coder_exit_event, NULL);
|
||||
|
||||
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
|
||||
s->current_status = AUCODEC_END;
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
|
||||
if(s->src_msi) {
|
||||
msi_del_output(s->src_msi, NULL, s->msi->name);
|
||||
s->src_msi = NULL;
|
||||
}
|
||||
|
||||
if(s->next_status != AUCODEC_EXIT)
|
||||
msi_destroy(s->msi);
|
||||
|
||||
msi_put(s->msi);
|
||||
}
|
||||
|
||||
static int32_t opus_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct opus_decode_struct *opus_decode_s = (struct opus_decode_struct *)(msi->priv);
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_AUCODER:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(opus_decode_s) {
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUCODER_PAUSE:
|
||||
{
|
||||
if(opus_decode_s->current_status == AUCODEC_RUN) {
|
||||
opus_decode_s->next_status = AUCODEC_PAUSE;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CONTINUE:
|
||||
{
|
||||
if(opus_decode_s->current_status == AUCODEC_PAUSE) {
|
||||
opus_decode_s->next_status = AUCODEC_RUN;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_STATUS:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(opus_decode_s->current_status);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SPEED:
|
||||
{
|
||||
opus_decode_s->speed = (uint8_t)param2;
|
||||
ret = msi_output_cmd(opus_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(opus_decode_s->speed));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_SPEED:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(opus_decode_s->speed);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_PITCH:
|
||||
{
|
||||
opus_decode_s->pitch = (uint8_t)param2;
|
||||
ret = msi_output_cmd(opus_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(opus_decode_s->pitch));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_PITCH:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(opus_decode_s->pitch);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CLEAR_STREAM:
|
||||
{
|
||||
os_event_set(&opus_decode_s->event, coder_clear_event, NULL);
|
||||
os_event_wait(&opus_decode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
msi_output_cmd(opus_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(opus_decode_s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_CLEAR_STREAM,(uint32_t)(&(opus_decode_s->audio_track)));
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SRCMSI:
|
||||
{
|
||||
if(opus_decode_s->src_msi) {
|
||||
msi_del_output(opus_decode_s->src_msi, NULL, msi->name);
|
||||
}
|
||||
opus_decode_s->src_msi = NULL;
|
||||
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
|
||||
if(ret == RET_OK) {
|
||||
opus_decode_s->src_msi = (struct msi*)param2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DIRECT_TO_DAC:
|
||||
{
|
||||
uint32_t direct_to_dac = param2;
|
||||
if(direct_to_dac && opus_decode_s->direct_to_dac == 0) {
|
||||
opus_decode_s->direct_to_dac = 1;
|
||||
if(opus_decode_s->use_tpc == 0) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(opus_decode_s->autpc_msi) {
|
||||
msi_add_output(opus_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(opus_decode_s->audio_track)));
|
||||
}
|
||||
else if(opus_decode_s->direct_to_dac == 1) {
|
||||
opus_decode_s->direct_to_dac = 0;
|
||||
if(opus_decode_s->use_tpc == 0) {
|
||||
msi_del_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(opus_decode_s->autpc_msi) {
|
||||
msi_del_output(opus_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
opus_decode_s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(opus_decode_s->audio_track)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DEINIT:
|
||||
{
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->mtype == F_AUDIO) {
|
||||
ret = RET_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(opus_decode_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->data) {
|
||||
OPUS_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
fbpool_put(&opus_decode_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if(opus_decode_s && opus_decode_s->task_hdl) {
|
||||
opus_decode_s->next_status = AUCODEC_EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(opus_decode_s) {
|
||||
if(opus_decode_s->task_hdl) {
|
||||
os_event_wait(&opus_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
}
|
||||
for(uint32_t i=0; i<MAX_OPUS_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (opus_decode_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
OPUS_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&opus_decode_s->tx_pool);
|
||||
if(opus_decode_s->event.hdl) {
|
||||
os_event_del(&opus_decode_s->event);
|
||||
}
|
||||
if(opus_decode_s->autpc_msi) {
|
||||
autpc_msi_deinit(opus_decode_s->autpc_msi);
|
||||
opus_decode_s->autpc_msi = NULL;
|
||||
}
|
||||
if(opus_decode_s->msi_name) {
|
||||
OPUS_CODE_FREE(opus_decode_s->msi_name);
|
||||
opus_decode_s->msi_name = NULL;
|
||||
}
|
||||
OPUS_CODE_FREE(opus_decode_s);
|
||||
opus_decode_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *opus_decode_init(uint32_t samplerate, AUDEC_INIT *audec_init)
|
||||
{
|
||||
#if AUDIO_EN
|
||||
char *msi_name = NULL;
|
||||
int32_t random_value = 0;
|
||||
|
||||
msi_name = (char*)OPUS_CODE_ZALLOC(sizeof(char)*32);
|
||||
if(msi_name == NULL) {
|
||||
os_printf("alloc autpc msi namefail\n");
|
||||
return NULL;
|
||||
}
|
||||
os_random_bytes((uint8_t*)(&random_value), 4);
|
||||
os_snprintf(msi_name, 20, "SR_OPUS_DECODE_""%04d", random_value);
|
||||
struct msi *msi = msi_new(msi_name, MAX_OPUS_DECODE_RXBUF, NULL);
|
||||
if(msi == NULL) {
|
||||
OPUS_INFO("create opus decode msi fail!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
struct opus_decode_struct *opus_decode_s = (struct opus_decode_struct *)OPUS_CODE_ZALLOC(sizeof(struct opus_decode_struct));
|
||||
if(!opus_decode_s) {
|
||||
OPUS_INFO("opus_decode_s malloc fail!\r\n");
|
||||
goto opus_decode_init_err;
|
||||
}
|
||||
msi->priv = opus_decode_s;
|
||||
msi->action = (msi_action)opus_decode_msi_action;
|
||||
fbpool_init(&opus_decode_s->tx_pool, MAX_OPUS_DECODE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_OPUS_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (opus_decode_s->tx_pool.pool)+i;
|
||||
frame_buf->data = NULL;
|
||||
frame_buf->priv = &(opus_decode_s->audio_track);
|
||||
}
|
||||
if(os_event_init(&opus_decode_s->event) != RET_OK) {
|
||||
OPUS_INFO("create opus decode event fail!\r\n");
|
||||
goto opus_decode_init_err;
|
||||
}
|
||||
if(audec_init->src_msi && (msi_add_output(audec_init->src_msi, NULL, msi->name) != RET_OK)) {
|
||||
goto opus_decode_init_err;
|
||||
}
|
||||
opus_decode_s->msi = msi;
|
||||
opus_decode_s->msi_name = msi_name;
|
||||
opus_decode_s->src_msi = audec_init->src_msi;
|
||||
opus_decode_s->direct_to_dac = audec_init->direct_to_dac;
|
||||
opus_decode_s->coder_sampleRate = samplerate;
|
||||
opus_decode_s->use_tpc = audec_init->use_tpc;
|
||||
opus_decode_s->speed = audec_init->speed;
|
||||
opus_decode_s->pitch = audec_init->pitch;
|
||||
opus_decode_s->destroy_self = audec_init->destroy_self;
|
||||
opus_decode_s->audio_track.priority = audec_init->priority;
|
||||
opus_decode_s->audio_track.track_type = audec_init->track_type;
|
||||
opus_decode_s->next_status = AUCODEC_RUN;
|
||||
opus_decode_s->current_status = AUCODEC_RUN;
|
||||
if(audec_init->direct_to_dac && !opus_decode_s->use_tpc) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
os_printf("opus_track:%x\n",&(opus_decode_s->audio_track));
|
||||
#if OPUS_DEC_CTRL == AUCODER_RUN_IN_CPU1
|
||||
opus_decode_s->task_hdl = os_task_create("opus_decode_thread", opus_decode_thread, (void*)opus_decode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
#else
|
||||
opus_decode_s->task_hdl = os_task_create("opus_decode_thread", opus_decode_thread, (void*)opus_decode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 2048);
|
||||
#endif
|
||||
if(opus_decode_s->task_hdl == NULL) {
|
||||
OPUS_INFO("create opus decode task fail!\r\n");
|
||||
goto opus_decode_init_err;
|
||||
}
|
||||
return msi;
|
||||
|
||||
opus_decode_init_err:
|
||||
msi_destroy(msi);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
378
sdk/app/audio_media_ctrl/opus/opus_encode.c
Normal file
378
sdk/app/audio_media_ctrl/opus/opus_encode.c
Normal file
@@ -0,0 +1,378 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/audio/audio_code/audio_code.h"
|
||||
#include "opus_code.h"
|
||||
|
||||
#define MAX_OPUS_ENCODE_RXBUF 4
|
||||
#define MAX_OPUS_ENCODE_TXBUF 14
|
||||
|
||||
#define FRAME_SIZE 160
|
||||
|
||||
struct opus_encode_struct {
|
||||
struct fbpool tx_pool;
|
||||
struct os_event event;
|
||||
struct msi *msi;
|
||||
struct msi *src_msi;
|
||||
void *task_hdl;
|
||||
uint8_t destroy_self;
|
||||
uint8_t next_status;
|
||||
uint8_t current_status;
|
||||
uint8_t enc_buf[1024];
|
||||
int16_t inbuf[FRAME_SIZE];
|
||||
uint32_t samplerate;
|
||||
uint32_t new_bitrate;
|
||||
uint32_t cur_bitrate;
|
||||
AUDIO_INFO audio_info;
|
||||
};
|
||||
|
||||
static void opus_encode_thread(void *d)
|
||||
{
|
||||
uint8_t clear_finish = 1;
|
||||
uint8_t get_audio_time = 0;
|
||||
uint8_t update_audio_time = 0;
|
||||
uint8_t *send_data = NULL;
|
||||
int16_t *recv_data = NULL;
|
||||
int32_t enc_bytes = 0;
|
||||
int32_t ret = 0;
|
||||
uint32_t data_len = 0;
|
||||
uint32_t data_offset = 0;
|
||||
uint32_t inbuf_offset = 0;
|
||||
uint32_t inbuf_reslen = (FRAME_SIZE << 1);
|
||||
uint32_t audio_time = 0;
|
||||
uint32_t clear_flag = 0;
|
||||
struct framebuff *send_frame_buf = NULL;
|
||||
struct framebuff *recv_frame_buf = NULL;
|
||||
struct opus_encode_struct *s = (struct opus_encode_struct *)d;
|
||||
AUCODE_HDL *opus_enc = NULL;
|
||||
|
||||
s->msi->enable = 1;
|
||||
msi_get(s->msi);
|
||||
|
||||
opus_enc = audio_coder_open(OPUS_ENC, s->samplerate, 1);
|
||||
if (opus_enc == NULL)
|
||||
goto opus_encode_thread_end;
|
||||
|
||||
s->audio_info.nsamples = FRAME_SIZE;
|
||||
s->audio_info.time_interval = s->audio_info.nsamples * FRAME_SIZE / s->samplerate;
|
||||
s->audio_info.samplerate = s->samplerate;
|
||||
|
||||
while(1) {
|
||||
os_event_wait(&s->event, coder_clear_event, &clear_flag, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, 0);
|
||||
if(clear_flag & coder_clear_event) {
|
||||
clear_flag = 0;
|
||||
clear_finish = 0;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
audio_coder_close(opus_enc);
|
||||
opus_enc = audio_coder_open(OPUS_ENC, s->samplerate, 1);
|
||||
if(opus_enc == NULL)
|
||||
goto opus_encode_thread_end;
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
inbuf_reslen = (FRAME_SIZE << 1);
|
||||
inbuf_offset = 0;
|
||||
}
|
||||
if(s->cur_bitrate != s->new_bitrate) {
|
||||
if(audio_encoder_set_bitrate(opus_enc, s->new_bitrate) == RET_OK) {
|
||||
s->cur_bitrate = s->new_bitrate;
|
||||
}
|
||||
}
|
||||
recv_frame_buf = msi_get_fb(s->msi, 0);
|
||||
if(recv_frame_buf) {
|
||||
if(clear_finish == 0) {
|
||||
inbuf_reslen = (FRAME_SIZE << 1);
|
||||
inbuf_offset = 0;
|
||||
goto opus_encode_frame_end;
|
||||
}
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
goto opus_encode_frame_end;
|
||||
}
|
||||
else {
|
||||
s->current_status = AUCODEC_RUN;
|
||||
recv_data = (int16_t*)recv_frame_buf->data;
|
||||
data_len = recv_frame_buf->len;
|
||||
data_offset = 0;
|
||||
if(!get_audio_time) {
|
||||
get_audio_time = 1;
|
||||
audio_time = recv_frame_buf->time;
|
||||
}
|
||||
if(update_audio_time) {
|
||||
audio_time = recv_frame_buf->time;
|
||||
update_audio_time = 0;
|
||||
}
|
||||
while(data_len >= inbuf_reslen) {
|
||||
os_memcpy(s->inbuf + (inbuf_offset/2), recv_data + (data_offset/2), inbuf_reslen);
|
||||
data_len -= inbuf_reslen;
|
||||
data_offset += inbuf_reslen;
|
||||
enc_bytes = audio_encode_data(opus_enc, s->inbuf, FRAME_SIZE, s->enc_buf);
|
||||
inbuf_reslen = (FRAME_SIZE << 1);
|
||||
inbuf_offset = 0;
|
||||
while(!send_frame_buf) {
|
||||
send_frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(!send_frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
if(send_frame_buf) {
|
||||
send_frame_buf->data = (uint8_t*)OPUS_CODE_MALLOC(enc_bytes);
|
||||
if(!send_frame_buf->data) {
|
||||
OPUS_INFO("opus encode malloc send_frame_buf->data fail!\n");
|
||||
msi_delete_fb(s->msi, send_frame_buf);
|
||||
send_frame_buf = NULL;
|
||||
goto opus_encode_frame_end;
|
||||
}
|
||||
send_data = send_frame_buf->data;
|
||||
os_memcpy(send_data, s->enc_buf, enc_bytes);
|
||||
send_frame_buf->len = enc_bytes;
|
||||
send_frame_buf->mtype = F_AUDIO;
|
||||
send_frame_buf->time = audio_time;
|
||||
send_frame_buf->priv = &(s->audio_info);
|
||||
ret = msi_output_fb(s->msi, send_frame_buf);
|
||||
OPUS_DEBUG("opus encode send framebuff:%p,ret:%d\r\n",send_frame_buf,ret);
|
||||
send_frame_buf = NULL;
|
||||
}
|
||||
audio_time += (FRAME_SIZE * 1000 / s->samplerate);
|
||||
if(data_len == 0)
|
||||
update_audio_time = 1;
|
||||
opus_encode_frame_end:
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
if(data_len) {
|
||||
os_memcpy(s->inbuf + (inbuf_offset/2), recv_data + (data_offset/2), data_len);
|
||||
inbuf_reslen -= data_len;
|
||||
inbuf_offset += data_len;
|
||||
data_offset = 0;
|
||||
data_len = 0;
|
||||
}
|
||||
}
|
||||
OPUS_DEBUG("opus encode delete framebuff:%p,len:%d,\r\n",recv_frame_buf,recv_frame_buf->len);
|
||||
msi_delete_fb(s->msi, recv_frame_buf);
|
||||
recv_frame_buf = NULL;
|
||||
}
|
||||
else {
|
||||
if(clear_finish == 0) {
|
||||
clear_finish = 1;
|
||||
os_event_set(&s->event, coder_clear_finish_event, NULL);
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
goto opus_encode_thread_end;
|
||||
}
|
||||
}
|
||||
opus_encode_thread_end:
|
||||
if(opus_enc)
|
||||
audio_coder_close(opus_enc);
|
||||
os_event_set(&s->event, coder_exit_event, NULL);
|
||||
|
||||
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
|
||||
s->current_status = AUCODEC_END;
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
|
||||
if(s->src_msi) {
|
||||
msi_del_output(s->src_msi, NULL, s->msi->name);
|
||||
s->src_msi = NULL;
|
||||
}
|
||||
|
||||
if(s->next_status != AUCODEC_EXIT)
|
||||
msi_destroy(s->msi);
|
||||
|
||||
msi_put(s->msi);
|
||||
}
|
||||
|
||||
static int32_t opus_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct opus_encode_struct *opus_encode_s = (struct opus_encode_struct*)(msi->priv);
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_AUCODER:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(opus_encode_s) {
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUCODER_PAUSE:
|
||||
{
|
||||
if(opus_encode_s->current_status == AUCODEC_RUN) {
|
||||
opus_encode_s->next_status = AUCODEC_PAUSE;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CONTINUE:
|
||||
{
|
||||
if(opus_encode_s->current_status == AUCODEC_PAUSE) {
|
||||
opus_encode_s->next_status = AUCODEC_RUN;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_STATUS:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(opus_encode_s->current_status);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_BITRATE:
|
||||
{
|
||||
opus_encode_s->new_bitrate = param2;
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CLEAR_STREAM:
|
||||
{
|
||||
os_event_set(&opus_encode_s->event, coder_clear_event, NULL);
|
||||
os_event_wait(&opus_encode_s->event, coder_clear_finish_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SRCMSI:
|
||||
{
|
||||
if(opus_encode_s->src_msi) {
|
||||
msi_del_output(opus_encode_s->src_msi, NULL, msi->name);
|
||||
}
|
||||
opus_encode_s->src_msi = NULL;
|
||||
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
|
||||
if(ret == RET_OK) {
|
||||
opus_encode_s->src_msi = (struct msi*)param2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DEINIT:
|
||||
{
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->mtype == F_AUDIO) {
|
||||
ret = RET_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(opus_encode_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->data) {
|
||||
OPUS_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
fbpool_put(&opus_encode_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if(opus_encode_s && opus_encode_s->task_hdl) {
|
||||
opus_encode_s->next_status = AUCODEC_EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(opus_encode_s) {
|
||||
if(opus_encode_s->task_hdl) {
|
||||
os_event_wait(&opus_encode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
}
|
||||
for(uint32_t i=0; i<MAX_OPUS_ENCODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (opus_encode_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
OPUS_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&opus_encode_s->tx_pool);
|
||||
if(opus_encode_s->event.hdl) {
|
||||
os_event_del(&opus_encode_s->event);
|
||||
}
|
||||
OPUS_CODE_FREE(opus_encode_s);
|
||||
opus_encode_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *opus_encode_init(uint32_t samplerate, AUENC_INIT *auenc_init)
|
||||
{
|
||||
#if AUDIO_EN
|
||||
uint8_t msi_isnew = 0;
|
||||
struct opus_encode_struct *opus_encode_s = NULL;
|
||||
|
||||
struct msi *msi = msi_new("SR_OPUS_ENCODE", MAX_OPUS_ENCODE_RXBUF, &msi_isnew);
|
||||
if(msi && !msi_isnew) {
|
||||
opus_encode_s = (struct opus_encode_struct*)(msi->priv);
|
||||
if(opus_encode_s) {
|
||||
if(samplerate != opus_encode_s->samplerate) {
|
||||
OPUS_INFO("opus_encode_init conflict!\r\n");
|
||||
goto opus_encode_init_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(msi && msi_isnew) {
|
||||
opus_encode_s = (struct opus_encode_struct*)OPUS_CODE_ZALLOC(sizeof(struct opus_encode_struct));
|
||||
if(!opus_encode_s) {
|
||||
OPUS_INFO("opus_encode_s malloc fail!\r\n");
|
||||
goto opus_encode_init_err;
|
||||
}
|
||||
msi->priv = opus_encode_s;
|
||||
msi->action = (msi_action)opus_encode_msi_action;
|
||||
fbpool_init(&opus_encode_s->tx_pool, MAX_OPUS_ENCODE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_OPUS_ENCODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (opus_encode_s->tx_pool.pool)+i;
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
if(os_event_init(&opus_encode_s->event) != RET_OK) {
|
||||
OPUS_INFO("create opus encode event fail!\r\n");
|
||||
goto opus_encode_init_err;
|
||||
}
|
||||
if(auenc_init->src_msi && (msi_add_output(auenc_init->src_msi, NULL, msi->name) != RET_OK)) {
|
||||
goto opus_encode_init_err;
|
||||
}
|
||||
opus_encode_s->msi = msi;
|
||||
opus_encode_s->src_msi = auenc_init->src_msi;
|
||||
opus_encode_s->samplerate = samplerate;
|
||||
opus_encode_s->destroy_self = auenc_init->destroy_self;
|
||||
opus_encode_s->next_status = AUCODEC_RUN;
|
||||
opus_encode_s->current_status = AUCODEC_RUN;
|
||||
}
|
||||
else {
|
||||
OPUS_INFO("create opus encode msi fail!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
if(msi_isnew) {
|
||||
#if OPUS_ENC_CTRL == AUCODER_RUN_IN_CPU1
|
||||
opus_encode_s->task_hdl = os_task_create("opus_encode_thread", opus_encode_thread, (void*)opus_encode_s, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
#else
|
||||
opus_encode_s->task_hdl = os_task_create("opus_encode_thread", opus_encode_thread, (void*)opus_encode_s, OS_TASK_PRIORITY_BELOW_NORMAL, 0, NULL, 3072);
|
||||
#endif
|
||||
if(opus_encode_s->task_hdl == NULL) {
|
||||
OPUS_INFO("create opus encode task fail!\r\n");
|
||||
goto opus_encode_init_err;
|
||||
}
|
||||
}
|
||||
return msi;
|
||||
|
||||
opus_encode_init_err:
|
||||
msi_destroy(msi);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
142
sdk/app/audio_media_ctrl/prompt_tone.c
Normal file
142
sdk/app/audio_media_ctrl/prompt_tone.c
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "prompt_tone.h"
|
||||
#include "audio_code_ctrl.h"
|
||||
|
||||
#define MAX_PROMPTTONE_TXBUF 4
|
||||
|
||||
static int32_t prompt_tone_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
PROMPT_TONE_STRUCT *tone_s = (PROMPT_TONE_STRUCT*)msi->priv;
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(tone_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
fbpool_put(&tone_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(tone_s) {
|
||||
for(uint32_t i=0; i<MAX_PROMPTTONE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (tone_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
PROMPTTONE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&tone_s->tx_pool);
|
||||
PROMPTTONE_FREE(tone_s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void prompt_tone_task(void *d)
|
||||
{
|
||||
struct framebuff *frame_buf = NULL;
|
||||
PROMPT_TONE_STRUCT *tone_s = (PROMPT_TONE_STRUCT*)d;
|
||||
|
||||
while(1) {
|
||||
if(audio_code_get_status(tone_s->mp3_msi) == AUCODEC_END) {
|
||||
msi_do_cmd(tone_s->mp3_msi, MSI_CMD_AUCODER, MSI_AUCODER_DEINIT, 0);
|
||||
break;
|
||||
}
|
||||
frame_buf = fbpool_get(&tone_s->tx_pool, 0, NULL);
|
||||
if(frame_buf) {
|
||||
if(tone_s->tone_buf_offset >= tone_s->tone_buf_size) {
|
||||
frame_buf->len = 0;
|
||||
}
|
||||
else if((tone_s->tone_buf_offset+1024) < tone_s->tone_buf_size) {
|
||||
os_memcpy(frame_buf->data, tone_s->tone_buf+tone_s->tone_buf_offset, 1024);
|
||||
frame_buf->len = 1024;
|
||||
tone_s->tone_buf_offset += 1024;
|
||||
}
|
||||
else {
|
||||
os_memcpy(frame_buf->data, tone_s->tone_buf+tone_s->tone_buf_offset,
|
||||
tone_s->tone_buf_size-tone_s->tone_buf_offset);
|
||||
frame_buf->len = tone_s->tone_buf_size-tone_s->tone_buf_offset;
|
||||
tone_s->tone_buf_offset = tone_s->tone_buf_size;
|
||||
}
|
||||
frame_buf->msi = tone_s->msi;
|
||||
frame_buf->mtype = F_AUDIO;
|
||||
msi_get(frame_buf->msi);
|
||||
msi_output_fb(tone_s->msi, frame_buf);
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
msi_destroy(tone_s->msi);
|
||||
}
|
||||
|
||||
struct msi *play_prompt_tone(const uint8_t *tone_buf, uint32_t size)
|
||||
{
|
||||
uint8_t msi_isnew = 0;
|
||||
struct framebuff *frame_buf = NULL;
|
||||
struct msi *tone_msi = NULL;
|
||||
struct msi *mp3_msi = NULL;
|
||||
AUDEC_INIT audec_init;
|
||||
|
||||
tone_msi = msi_new("S_PROMPTTONE", MAX_PROMPTTONE_TXBUF, &msi_isnew);
|
||||
if(tone_msi == NULL) {
|
||||
os_printf("create prompt_tone msi fail\n");
|
||||
return NULL;
|
||||
}
|
||||
if(tone_msi && !msi_isnew) {
|
||||
os_printf("prompt_tone msi has been created\n");
|
||||
return NULL;
|
||||
}
|
||||
PROMPT_TONE_STRUCT *tone_s = (PROMPT_TONE_STRUCT*)PROMPTTONE_ZALLOC(sizeof(PROMPT_TONE_STRUCT));
|
||||
if(tone_s == NULL) {
|
||||
os_printf("malloc tone_s fail!\n");
|
||||
goto play_prompt_tone_err;
|
||||
}
|
||||
tone_s->msi = tone_msi;
|
||||
tone_s->msi->enable = 1;
|
||||
tone_s->msi->action = prompt_tone_msi_action;
|
||||
tone_s->tone_buf = tone_buf;
|
||||
tone_s->tone_buf_size = size;
|
||||
|
||||
fbpool_init(&tone_s->tx_pool, MAX_PROMPTTONE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_PROMPTTONE_TXBUF; i++) {
|
||||
frame_buf = (tone_s->tx_pool.pool)+i;
|
||||
frame_buf->data = (uint8_t*)PROMPTTONE_MALLOC(sizeof(uint8_t) * 1024);
|
||||
if(!frame_buf->data)
|
||||
goto play_prompt_tone_err;
|
||||
}
|
||||
tone_s->msi->priv = tone_s;
|
||||
audec_init.track_type = BELL_TRACK;
|
||||
audec_init.priority = play_interruptible;
|
||||
audec_init.direct_to_dac = 1;
|
||||
audec_init.use_tpc = 0;
|
||||
audec_init.destroy_self = 0;
|
||||
audec_init.src_msi = tone_msi;
|
||||
mp3_msi = audio_decode_init(MP3_DEC, 0, &audec_init);
|
||||
if(mp3_msi == NULL) {
|
||||
os_printf("tone_s create mp3 msi fail!\n");
|
||||
goto play_prompt_tone_err;
|
||||
}
|
||||
msi_add_output(tone_msi, NULL, mp3_msi->name);
|
||||
tone_s->mp3_msi = mp3_msi;
|
||||
tone_s->task_hdl = os_task_create("prompt_tone_task", prompt_tone_task, (void*)tone_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||||
if(tone_s->task_hdl == NULL) {
|
||||
os_printf("create tone_s task fail!\r\n");
|
||||
goto play_prompt_tone_err;
|
||||
}
|
||||
return tone_msi;
|
||||
play_prompt_tone_err:
|
||||
if(tone_msi)
|
||||
msi_destroy(tone_msi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void play_prompt_tone_test(void)
|
||||
{
|
||||
play_prompt_tone(connect_mp3, 2969);
|
||||
}
|
||||
33
sdk/app/audio_media_ctrl/prompt_tone.h
Normal file
33
sdk/app/audio_media_ctrl/prompt_tone.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef _PROMPT_TONE_H_
|
||||
#define _PROMPT_TONE_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define PROMPTTONE_MALLOC av_psram_malloc
|
||||
#define PROMPTTONE_ZALLOC av_psram_zalloc
|
||||
#define PROMPTTONE_FREE av_psram_free
|
||||
#else
|
||||
#define PROMPTTONE_MALLOC av_malloc
|
||||
#define PROMPTTONE_ZALLOC av_zalloc
|
||||
#define PROMPTTONE_FREE av_free
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *tone_buf;
|
||||
void *task_hdl;
|
||||
uint32_t tone_buf_size;
|
||||
uint32_t tone_buf_offset;
|
||||
struct fbpool tx_pool;
|
||||
struct msi *msi;
|
||||
struct msi *mp3_msi;
|
||||
} PROMPT_TONE_STRUCT;
|
||||
|
||||
extern const uint8_t connect_mp3[];
|
||||
extern const uint8_t disconnect_mp3[];
|
||||
|
||||
#endif
|
||||
607
sdk/app/audio_media_ctrl/prompt_tone_demon.c
Normal file
607
sdk/app/audio_media_ctrl/prompt_tone_demon.c
Normal file
@@ -0,0 +1,607 @@
|
||||
#include "basic_include.h"
|
||||
#include "prompt_tone.h"
|
||||
|
||||
const uint8_t connect_mp3[] = {
|
||||
0xff, 0xf3, 0x2a, 0xc0, 0x00, 0x00, 0x00, 0x02,
|
||||
0x5c, 0x00, 0x00, 0x00, 0x00, 0x12, 0x49, 0x10,
|
||||
0x52, 0x45, 0x09, 0x20, 0x44, 0x3b, 0x00, 0x7c,
|
||||
0x50, 0x9c, 0xd7, 0x63, 0xe9, 0x88, 0xbe, 0xdf,
|
||||
0x74, 0xee, 0xef, 0x3f, 0xcf, 0xb5, 0x71, 0x9a,
|
||||
0xcf, 0xff, 0xb1, 0xb8, 0x7e, 0x7d, 0xee, 0xa5,
|
||||
0x9a, 0x7d, 0x82, 0x4d, 0x63, 0x9c, 0xcf, 0xdd,
|
||||
0xca, 0x7b, 0x19, 0xf5, 0x35, 0x65, 0x14, 0xb4,
|
||||
0x9a, 0xef, 0xfe, 0xf5, 0x86, 0xf3, 0xec, 0xfb,
|
||||
0xe9, 0xff, 0xf3, 0x38, 0xc0, 0x3c, 0x00, 0x00,
|
||||
0x02, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x6e,
|
||||
0x6e, 0x4f, 0x12, 0x7d, 0x98, 0x6f, 0x33, 0xff,
|
||||
0xff, 0xf0, 0xe0, 0x30, 0x37, 0x9d, 0xaf, 0xda,
|
||||
0xb1, 0xd5, 0x01, 0x3c, 0x51, 0x88, 0x53, 0x43,
|
||||
0xd2, 0xb3, 0xde, 0x18, 0x57, 0x6a, 0x3f, 0xc9,
|
||||
0xbd, 0x3c, 0x48, 0x2a, 0x28, 0xd6, 0x7f, 0xa0,
|
||||
0x3f, 0x38, 0x8b, 0xae, 0x34, 0x09, 0x52, 0x57,
|
||||
0xce, 0xe0, 0x02, 0x7d, 0x28, 0xaf, 0xa1, 0x43,
|
||||
0x29, 0x7e, 0xcc, 0xa2, 0xb7, 0xcc, 0xbf, 0xea,
|
||||
0xcc, 0x3e, 0xf1, 0xa4, 0x38, 0x09, 0x91, 0x6a,
|
||||
0x6f, 0xed, 0x2d, 0xec, 0xb1, 0xff, 0xc7, 0x5d,
|
||||
0xde, 0xbb, 0x96, 0xff, 0xbf, 0xfd, 0xb9, 0xba,
|
||||
0x6b, 0xf9, 0x6a, 0xaf, 0xda, 0xff, 0xf3, 0x2a,
|
||||
0xc0, 0x9b, 0x00, 0x00, 0x02, 0x5c, 0x01, 0x40,
|
||||
0x00, 0x00, 0xe5, 0x5a, 0x48, 0x55, 0xfc, 0x1a,
|
||||
0x50, 0xa9, 0x12, 0xdc, 0xa3, 0xeb, 0xfb, 0x26,
|
||||
0xdd, 0xaf, 0x34, 0xcb, 0x3f, 0xff, 0x52, 0x10,
|
||||
0xaa, 0xff, 0x5e, 0xa2, 0x8f, 0xff, 0x58, 0xb8,
|
||||
0x5a, 0xaa, 0xeb, 0xeb, 0x93, 0x00, 0x36, 0x7d,
|
||||
0x74, 0x59, 0x07, 0x6a, 0x08, 0x9a, 0xea, 0xbb,
|
||||
0xa9, 0x74, 0xd9, 0x24, 0x4f, 0x4c, 0x53, 0x44,
|
||||
0x42, 0x61, 0x3f, 0x01, 0x14, 0x00, 0xff, 0xf3,
|
||||
0x38, 0xc0, 0xd7, 0x1a, 0xb9, 0x72, 0xa9, 0x97,
|
||||
0x8b, 0xc3, 0x02, 0x77, 0xc1, 0x86, 0x32, 0x22,
|
||||
0xa1, 0x97, 0xb0, 0xe9, 0x10, 0xea, 0x84, 0xa7,
|
||||
0x4f, 0xf0, 0x20, 0xcc, 0x44, 0xf1, 0xef, 0xbc,
|
||||
0xf0, 0xa4, 0xa7, 0x37, 0x21, 0x38, 0xae, 0x6e,
|
||||
0x32, 0x58, 0xb3, 0x59, 0xe9, 0x2e, 0x94, 0x51,
|
||||
0xb8, 0x6b, 0x96, 0x28, 0x04, 0xd0, 0x2a, 0xb5,
|
||||
0xc8, 0x93, 0xff, 0xd4, 0xc2, 0x83, 0x95, 0xb1,
|
||||
0x9a, 0x94, 0x06, 0x5e, 0x32, 0xce, 0x50, 0x0a,
|
||||
0xaf, 0xf4, 0xd2, 0x53, 0xa6, 0xb5, 0xa0, 0xee,
|
||||
0xee, 0xce, 0x85, 0x2b, 0xdd, 0xaa, 0x52, 0x09,
|
||||
0x12, 0x2b, 0x1f, 0x01, 0x1b, 0x0e, 0x14, 0x97,
|
||||
0xfe, 0x5e, 0x91, 0xc2, 0xcd, 0xac, 0x5a, 0xc9,
|
||||
0xbc, 0x41, 0xff, 0xf3, 0x2a, 0xc0, 0xcb, 0x13,
|
||||
0x69, 0x4e, 0xb1, 0x8f, 0xc2, 0xd0, 0x02, 0x58,
|
||||
0x67, 0xab, 0x71, 0x02, 0x89, 0x29, 0x01, 0x20,
|
||||
0x75, 0x2b, 0x76, 0xbb, 0x88, 0xcc, 0x35, 0xe5,
|
||||
0x54, 0xae, 0x86, 0x81, 0x88, 0x5c, 0x9c, 0x74,
|
||||
0xb3, 0x12, 0xc1, 0xdd, 0x2f, 0x8a, 0x6e, 0x2d,
|
||||
0xd2, 0x55, 0x9e, 0x50, 0x4a, 0x50, 0x00, 0x6b,
|
||||
0xfe, 0xeb, 0x5f, 0x2d, 0xa7, 0x2a, 0xb2, 0x34,
|
||||
0xb7, 0xda, 0xfd, 0xf1, 0xda, 0x9a, 0x71, 0x58,
|
||||
0xb8, 0xf2, 0xe5, 0xff, 0xf3, 0x38, 0xc0, 0xb9,
|
||||
0x15, 0x39, 0x3e, 0xb1, 0x96, 0xa0, 0xf1, 0x2a,
|
||||
0x94, 0x22, 0xfe, 0x2d, 0x8b, 0xb2, 0xfa, 0xa7,
|
||||
0x4e, 0x20, 0x60, 0x8a, 0xcf, 0xdd, 0x6b, 0x4d,
|
||||
0x68, 0x9e, 0x66, 0x6a, 0x2f, 0xb6, 0x70, 0x0f,
|
||||
0x04, 0x49, 0x4e, 0x6e, 0xfe, 0x90, 0x45, 0x22,
|
||||
0xa0, 0xe3, 0x58, 0xd3, 0xa4, 0x9f, 0x0d, 0x6f,
|
||||
0x67, 0xac, 0x70, 0xa3, 0x6c, 0x10, 0x2d, 0xbb,
|
||||
0x35, 0x4c, 0x17, 0xa6, 0x71, 0xba, 0x80, 0x05,
|
||||
0x96, 0x51, 0x96, 0x52, 0x80, 0x1b, 0xff, 0xf9,
|
||||
0xfa, 0xb6, 0x87, 0xf6, 0x7b, 0xdd, 0xe2, 0x61,
|
||||
0xb8, 0xba, 0x98, 0xae, 0xe2, 0x58, 0x5e, 0x67,
|
||||
0x1e, 0xc4, 0x8a, 0xf6, 0xfa, 0xfd, 0x6f, 0x64,
|
||||
0xf6, 0xa2, 0x93, 0xa9, 0x15, 0xaa, 0xe8, 0xff,
|
||||
0xf3, 0x2a, 0xc0, 0xc3, 0x12, 0x79, 0x36, 0x9d,
|
||||
0x76, 0x98, 0xf1, 0x46, 0x19, 0xd2, 0xa2, 0x4a,
|
||||
0x00, 0x6c, 0x26, 0x1b, 0x5c, 0x86, 0x3e, 0xfd,
|
||||
0xc0, 0x73, 0x0e, 0x6e, 0x53, 0x2e, 0xdb, 0xbd,
|
||||
0x1a, 0x9c, 0xc3, 0x8d, 0x1d, 0x28, 0xba, 0x6c,
|
||||
0x33, 0x59, 0x6a, 0xda, 0xde, 0xb0, 0x7f, 0x94,
|
||||
0x92, 0x94, 0x00, 0x67, 0x77, 0x39, 0xdd, 0x75,
|
||||
0x22, 0xad, 0x55, 0xdc, 0x8a, 0xae, 0x42, 0xad,
|
||||
0x57, 0x4d, 0x03, 0xaa, 0x22, 0xe5, 0x11, 0x0a,
|
||||
0xff, 0xf3, 0x38, 0xc0, 0xb5, 0x14, 0x11, 0x36,
|
||||
0x95, 0x76, 0x36, 0x65, 0x02, 0x81, 0xda, 0x23,
|
||||
0x22, 0x5b, 0x46, 0xdf, 0x52, 0x0a, 0xa0, 0x7d,
|
||||
0x14, 0x4f, 0x2c, 0xfa, 0x6c, 0x82, 0xdd, 0x06,
|
||||
0x4c, 0xc9, 0x6e, 0x9b, 0xb1, 0x80, 0xe4, 0x01,
|
||||
0xb8, 0x22, 0xe1, 0x36, 0x94, 0x47, 0xf9, 0x56,
|
||||
0x12, 0x2d, 0x4a, 0xda, 0xe7, 0x5f, 0xed, 0xf2,
|
||||
0xa0, 0x42, 0xaf, 0x66, 0x01, 0xf9, 0xb5, 0xad,
|
||||
0x00, 0x43, 0x2c, 0x35, 0x17, 0x5e, 0x40, 0xd2,
|
||||
0xc3, 0xeb, 0x00, 0x5e, 0x7e, 0x0f, 0x33, 0x45,
|
||||
0x3b, 0xc7, 0x6f, 0x6d, 0x39, 0xf7, 0xaf, 0xe4,
|
||||
0xe6, 0x1d, 0xa0, 0x10, 0x25, 0xff, 0x8c, 0xb8,
|
||||
0x0c, 0x5a, 0xbb, 0x83, 0xd7, 0x09, 0xd4, 0xe3,
|
||||
0xe7, 0x11, 0x50, 0x6c, 0xff, 0xf3, 0x2a, 0xc0,
|
||||
0xc3, 0x12, 0x61, 0x36, 0x9d, 0x96, 0x46, 0xa1,
|
||||
0x02, 0xee, 0x6f, 0xfb, 0x63, 0xe9, 0x21, 0x88,
|
||||
0x73, 0x95, 0xa4, 0x52, 0xe6, 0x0d, 0x6f, 0xf5,
|
||||
0xfd, 0xe1, 0xa2, 0x3a, 0x6b, 0xdb, 0x77, 0x25,
|
||||
0x98, 0x44, 0xc1, 0x5b, 0xbf, 0x56, 0x6a, 0xe3,
|
||||
0x5a, 0xdf, 0xff, 0xff, 0xfc, 0xf7, 0xff, 0xff,
|
||||
0xdd, 0xd6, 0x8f, 0xe7, 0x1d, 0xcc, 0x3c, 0xf2,
|
||||
0x39, 0x9e, 0xeb, 0xbf, 0x9f, 0xfe, 0xef, 0xd6,
|
||||
0x59, 0x7f, 0xac, 0x40, 0x60, 0xff, 0xf3, 0x38,
|
||||
0xc0, 0xb5, 0x13, 0x59, 0x3e, 0x98, 0xd7, 0x45,
|
||||
0x98, 0x02, 0x03, 0x93, 0x64, 0xdf, 0x8b, 0x8b,
|
||||
0xb4, 0x9a, 0xee, 0x1d, 0x57, 0xa6, 0x60, 0x78,
|
||||
0x00, 0xc0, 0x03, 0x09, 0xf8, 0x0f, 0x8d, 0x0c,
|
||||
0x2a, 0x5d, 0x40, 0xc9, 0x27, 0x71, 0xf4, 0x1a,
|
||||
0x0a, 0x4b, 0x6a, 0xe6, 0xaa, 0x2f, 0x24, 0xba,
|
||||
0x24, 0xea, 0x4c, 0x5d, 0x2e, 0x08, 0xe0, 0x31,
|
||||
0x50, 0xa0, 0x85, 0xcc, 0x7f, 0xb7, 0xeb, 0xa2,
|
||||
0x51, 0x20, 0x89, 0x7f, 0xff, 0xff, 0xff, 0xf5,
|
||||
0xa4, 0x70, 0xd8, 0xf7, 0xff, 0xff, 0xfc, 0x35,
|
||||
0x22, 0x40, 0x4a, 0xa8, 0x09, 0xaf, 0x03, 0x00,
|
||||
0x06, 0x37, 0xb9, 0x76, 0x06, 0x62, 0xa5, 0x59,
|
||||
0xcc, 0x3f, 0xad, 0x21, 0x84, 0x11, 0x54, 0x60,
|
||||
0x87, 0xff, 0xf3, 0x2a, 0xc0, 0xc6, 0x18, 0x79,
|
||||
0x62, 0xc1, 0x97, 0x88, 0xc8, 0x02, 0xb9, 0xf1,
|
||||
0x7c, 0x32, 0x6a, 0x5a, 0x48, 0x4d, 0x54, 0xce,
|
||||
0x8a, 0xea, 0x36, 0xd2, 0x2c, 0x01, 0x51, 0xa4,
|
||||
0x4c, 0x96, 0x27, 0x9d, 0x25, 0xf6, 0x5a, 0xea,
|
||||
0xb3, 0x9d, 0x13, 0xd1, 0x22, 0xff, 0xdb, 0x43,
|
||||
0x55, 0x9c, 0x84, 0x92, 0xf6, 0xf5, 0xdb, 0x1a,
|
||||
0x0a, 0x24, 0xe7, 0x7f, 0xff, 0xff, 0xfc, 0x4a,
|
||||
0xfa, 0xf9, 0x52, 0xbf, 0xbf, 0x80, 0x14, 0x6c,
|
||||
0xc2, 0x7e, 0xff, 0xf3, 0x38, 0xc0, 0xa0, 0x13,
|
||||
0x31, 0xd2, 0xc1, 0x77, 0xc8, 0x98, 0x02, 0x15,
|
||||
0x41, 0x49, 0x23, 0xee, 0x90, 0xb7, 0x03, 0x5f,
|
||||
0x05, 0xa7, 0xad, 0x1b, 0x5a, 0x5f, 0x0d, 0x39,
|
||||
0xdb, 0xff, 0xad, 0x25, 0xb1, 0x78, 0x1a, 0x48,
|
||||
0x61, 0x33, 0xaf, 0x57, 0xf9, 0xd6, 0xbd, 0x47,
|
||||
0x7a, 0x32, 0xd4, 0x0f, 0x8b, 0x5c, 0xef, 0x4f,
|
||||
0xa3, 0x8b, 0xa5, 0xab, 0x38, 0xd5, 0x55, 0x91,
|
||||
0x15, 0x7c, 0xcb, 0xca, 0x23, 0x90, 0xb9, 0x75,
|
||||
0x50, 0xde, 0xe5, 0x80, 0x7e, 0xbd, 0x59, 0xaf,
|
||||
0x97, 0x80, 0x1c, 0xa7, 0x0f, 0x22, 0x20, 0x92,
|
||||
0x21, 0xe3, 0xb2, 0xcf, 0x0d, 0xb0, 0x68, 0xd8,
|
||||
0x1b, 0x1a, 0x37, 0x6e, 0x8a, 0x21, 0xa4, 0x36,
|
||||
0x0f, 0x59, 0x4f, 0xa9, 0x7d, 0x49, 0xff, 0xf3,
|
||||
0x2a, 0xc0, 0xb2, 0x12, 0x39, 0xd2, 0xb1, 0x96,
|
||||
0x2d, 0x0a, 0xda, 0x33, 0xc8, 0xa0, 0x24, 0xdd,
|
||||
0x25, 0x77, 0x7f, 0xf9, 0x99, 0x14, 0xd7, 0x58,
|
||||
0x72, 0xd8, 0x08, 0x8a, 0xc2, 0x4b, 0x8a, 0x2a,
|
||||
0x8b, 0x2f, 0x59, 0x17, 0xd5, 0xa3, 0xc0, 0xc4,
|
||||
0x3d, 0xbf, 0xd6, 0x3f, 0xb7, 0x73, 0xa8, 0x40,
|
||||
0x59, 0xa8, 0x05, 0x6b, 0x77, 0x00, 0x19, 0x77,
|
||||
0xa4, 0xd2, 0x4c, 0xa4, 0x62, 0x3a, 0x19, 0x51,
|
||||
0xfa, 0x03, 0x6c, 0x21, 0x54, 0x0a, 0x08, 0xff,
|
||||
0xf3, 0x38, 0xc0, 0xa5, 0x11, 0x89, 0x3a, 0xbd,
|
||||
0x96, 0x0c, 0xde, 0xd6, 0x3d, 0xf4, 0x49, 0x91,
|
||||
0x2d, 0x2d, 0x5e, 0xd4, 0xea, 0xdd, 0x4b, 0x6a,
|
||||
0x42, 0xf4, 0x0d, 0x43, 0x74, 0xaa, 0xaf, 0xf7,
|
||||
0xa1, 0x49, 0x01, 0x86, 0x5e, 0x4c, 0xdb, 0x23,
|
||||
0xcc, 0x11, 0xdc, 0xd9, 0x26, 0xde, 0x44, 0x80,
|
||||
0xc5, 0x9e, 0xa9, 0x34, 0x5d, 0xf3, 0x0d, 0x8a,
|
||||
0xac, 0xf1, 0x85, 0xfb, 0xde, 0xad, 0x20, 0x7f,
|
||||
0xfd, 0x9a, 0xff, 0x9b, 0x80, 0xb4, 0x36, 0x49,
|
||||
0x42, 0x43, 0x11, 0x26, 0x9c, 0x67, 0xb1, 0xb0,
|
||||
0xb7, 0x00, 0xf9, 0x80, 0x14, 0x64, 0xb0, 0xb5,
|
||||
0x69, 0xe3, 0x9b, 0x43, 0x56, 0xd7, 0x75, 0xba,
|
||||
0x49, 0x32, 0xce, 0x88, 0xec, 0x9c, 0xb5, 0x55,
|
||||
0xe6, 0xa3, 0x4e, 0xff, 0xf3, 0x2a, 0xc0, 0xbd,
|
||||
0x11, 0xa9, 0x3a, 0xb1, 0x96, 0x0d, 0x1a, 0xc6,
|
||||
0x55, 0x9e, 0x19, 0x01, 0x13, 0x50, 0x85, 0xde,
|
||||
0xe7, 0x1d, 0x43, 0xf8, 0xcd, 0x9b, 0xb5, 0xae,
|
||||
0xfb, 0x7d, 0xa6, 0x10, 0x75, 0xcc, 0x00, 0xa3,
|
||||
0xec, 0x1f, 0x41, 0x3b, 0x52, 0xaa, 0xb9, 0x5a,
|
||||
0xbf, 0x97, 0x80, 0x26, 0x3f, 0xa9, 0x6c, 0x65,
|
||||
0xcc, 0xc8, 0x89, 0xe9, 0x33, 0x3a, 0xcf, 0x8a,
|
||||
0x58, 0x05, 0xc9, 0x00, 0x34, 0xf1, 0xdc, 0x8b,
|
||||
0xb7, 0x50, 0x75, 0x8a, 0xff, 0xf3, 0x38, 0xc0,
|
||||
0xb2, 0x12, 0x59, 0x3a, 0xa5, 0x96, 0x2d, 0x22,
|
||||
0xc6, 0x8d, 0x53, 0xad, 0xea, 0xa6, 0xb7, 0x53,
|
||||
0x32, 0x83, 0xfe, 0x03, 0x41, 0x8c, 0x7a, 0xd5,
|
||||
0xfe, 0x99, 0x7f, 0x14, 0x2b, 0x75, 0xfc, 0x2b,
|
||||
0x06, 0x5c, 0x2e, 0x50, 0x55, 0x62, 0xba, 0xe5,
|
||||
0xd5, 0xe8, 0x31, 0x5b, 0xff, 0xae, 0x8b, 0x77,
|
||||
0xfd, 0x26, 0x0c, 0x1b, 0x73, 0xd0, 0x64, 0x5e,
|
||||
0x69, 0x58, 0xa4, 0xdb, 0x80, 0x39, 0xab, 0x37,
|
||||
0x13, 0x9b, 0x1d, 0xa0, 0x1e, 0xb5, 0x90, 0xd2,
|
||||
0x04, 0x28, 0x40, 0x37, 0x20, 0x09, 0x26, 0xef,
|
||||
0x21, 0xe2, 0x03, 0x8c, 0x44, 0xe8, 0xa2, 0xc9,
|
||||
0xdd, 0x07, 0xd1, 0x5a, 0x4a, 0x16, 0x90, 0xb1,
|
||||
0x91, 0xde, 0x1e, 0x5e, 0x57, 0x2a, 0x2d, 0x57,
|
||||
0xff, 0xf3, 0x2a, 0xc0, 0xc7, 0x12, 0x39, 0x32,
|
||||
0xb5, 0x96, 0x0d, 0x14, 0xd2, 0x40, 0x08, 0x1c,
|
||||
0x3f, 0x92, 0x06, 0x81, 0xf3, 0xc0, 0x20, 0x01,
|
||||
0xf7, 0x8f, 0x25, 0x85, 0x5a, 0xa0, 0x08, 0x88,
|
||||
0xac, 0x54, 0xb1, 0x5a, 0xbf, 0x43, 0x29, 0xfe,
|
||||
0x2b, 0x53, 0x98, 0x05, 0x3c, 0x88, 0x6a, 0x31,
|
||||
0xd2, 0x62, 0x84, 0x23, 0x3a, 0xe5, 0x13, 0x30,
|
||||
0x16, 0x80, 0x8d, 0x13, 0xaf, 0x4a, 0xcc, 0x3e,
|
||||
0x48, 0x54, 0x6b, 0xaf, 0x55, 0x05, 0x59, 0x6a,
|
||||
0x43, 0xff, 0xf3, 0x38, 0xc0, 0xba, 0x13, 0x31,
|
||||
0x3e, 0xad, 0x96, 0x1d, 0x18, 0xd6, 0x0b, 0x38,
|
||||
0x1e, 0x26, 0x76, 0xb1, 0x3b, 0x17, 0x73, 0xa8,
|
||||
0xd0, 0x04, 0x0c, 0x09, 0x38, 0x50, 0x54, 0x89,
|
||||
0x02, 0xc3, 0x83, 0xee, 0x84, 0xea, 0x46, 0xf9,
|
||||
0x82, 0xc9, 0x48, 0xf4, 0xb8, 0xd3, 0xd0, 0xea,
|
||||
0x9a, 0x84, 0x3d, 0xbf, 0xf2, 0x25, 0x58, 0xca,
|
||||
0x75, 0x00, 0x55, 0x6c, 0xb5, 0x4e, 0x60, 0x08,
|
||||
0x72, 0xcc, 0x54, 0x64, 0x35, 0x22, 0x0e, 0x1a,
|
||||
0x08, 0x1f, 0x2e, 0x0c, 0xb8, 0x24, 0x90, 0x58,
|
||||
0x11, 0x75, 0xab, 0x62, 0x89, 0x10, 0x65, 0x21,
|
||||
0xe8, 0xa6, 0xf5, 0x5f, 0x5a, 0x83, 0xda, 0x22,
|
||||
0x9c, 0x4a, 0x57, 0xc2, 0xf5, 0x0d, 0xd1, 0x28,
|
||||
0x12, 0xb8, 0xec, 0xe1, 0xd3, 0xff, 0xf3, 0x2a,
|
||||
0xc0, 0xcc, 0x12, 0xc1, 0x36, 0xa7, 0x86, 0x0d,
|
||||
0x0a, 0xd2, 0xc5, 0xa1, 0x55, 0xd2, 0x96, 0x80,
|
||||
0x14, 0x72, 0xb4, 0x39, 0xb1, 0x94, 0xa5, 0xf6,
|
||||
0x7c, 0x3c, 0xca, 0xbf, 0xd6, 0x64, 0x95, 0xf5,
|
||||
0x80, 0x56, 0xa9, 0x5a, 0xaf, 0x77, 0x00, 0xe6,
|
||||
0x4a, 0x7b, 0x7a, 0x3f, 0x34, 0x1b, 0x85, 0xc3,
|
||||
0xa9, 0x64, 0x60, 0xd2, 0x03, 0x3d, 0x00, 0x6f,
|
||||
0x04, 0x83, 0x3a, 0x90, 0x65, 0xc4, 0xfa, 0xca,
|
||||
0x7e, 0x8b, 0xb2, 0x74, 0xd0, 0x52, 0xff, 0xf3,
|
||||
0x38, 0xc0, 0xbd, 0x13, 0x49, 0x36, 0x98, 0xd6,
|
||||
0x0c, 0x4a, 0xd2, 0x6e, 0x5f, 0x29, 0x87, 0x44,
|
||||
0x2e, 0x13, 0x1b, 0x53, 0xee, 0x59, 0x2e, 0xb9,
|
||||
0x44, 0x34, 0xd2, 0x66, 0x62, 0xb0, 0x28, 0x40,
|
||||
0x44, 0x75, 0x87, 0x0b, 0x01, 0xca, 0x19, 0x69,
|
||||
0x73, 0x49, 0xb2, 0xc0, 0xf5, 0x3f, 0x86, 0xc0,
|
||||
0xe2, 0x72, 0xee, 0x40, 0x61, 0x6c, 0x4f, 0x70,
|
||||
0x7a, 0x80, 0x7a, 0xa5, 0x59, 0xab, 0x77, 0x81,
|
||||
0x12, 0x20, 0xa3, 0x41, 0x64, 0xcc, 0x88, 0x44,
|
||||
0x4d, 0xcf, 0x59, 0x7d, 0x1b, 0xfc, 0xf0, 0x00,
|
||||
0x8b, 0x96, 0x37, 0xf1, 0xe3, 0x79, 0x02, 0xbe,
|
||||
0xa3, 0x7b, 0x63, 0xae, 0x7f, 0x9f, 0x93, 0x10,
|
||||
0x61, 0xd7, 0x0e, 0x67, 0x4d, 0xbd, 0xb5, 0xde,
|
||||
0xe6, 0x28, 0xff, 0xf3, 0x2a, 0xc0, 0xce, 0x12,
|
||||
0x49, 0x3e, 0x9d, 0x76, 0x0d, 0x10, 0xd2, 0x74,
|
||||
0x6a, 0x8f, 0x69, 0x72, 0x90, 0xfb, 0x52, 0x5d,
|
||||
0x0f, 0x34, 0x41, 0x72, 0x68, 0xb8, 0xfe, 0xcf,
|
||||
0x91, 0xb7, 0xd3, 0xa3, 0x24, 0x40, 0xfd, 0x46,
|
||||
0x49, 0x26, 0xe2, 0x3d, 0xcc, 0xe0, 0x6a, 0xf1,
|
||||
0xca, 0xc2, 0x77, 0x2e, 0xf7, 0xa0, 0x98, 0x9f,
|
||||
0x05, 0xdc, 0x56, 0x46, 0xcb, 0x55, 0x44, 0xe9,
|
||||
0x24, 0xe5, 0xda, 0x08, 0xaa, 0x83, 0x50, 0x49,
|
||||
0x23, 0x14, 0x10, 0xff, 0xf3, 0x38, 0xc0, 0xc0,
|
||||
0x14, 0xe1, 0x6a, 0xa1, 0x96, 0x1c, 0xc4, 0xd2,
|
||||
0x14, 0x28, 0x68, 0x2c, 0xc2, 0x15, 0xe2, 0x1b,
|
||||
0x21, 0xa3, 0xa9, 0x13, 0x99, 0x11, 0xef, 0x63,
|
||||
0xc8, 0xda, 0xe4, 0x48, 0xf9, 0x1c, 0xdf, 0x81,
|
||||
0x90, 0x1a, 0x79, 0x70, 0xe9, 0x21, 0x77, 0x86,
|
||||
0xd0, 0x5c, 0xa9, 0x4b, 0x4d, 0xd5, 0xc8, 0x80,
|
||||
0x56, 0xa6, 0x09, 0x37, 0x24, 0xf0, 0x8e, 0x6c,
|
||||
0x46, 0xb9, 0xd7, 0x51, 0xea, 0x9e, 0x49, 0x62,
|
||||
0xc3, 0x73, 0x59, 0x35, 0x40, 0x7f, 0x11, 0xc8,
|
||||
0x38, 0xce, 0x31, 0x8c, 0xed, 0x25, 0x8c, 0xfb,
|
||||
0x53, 0xe3, 0xee, 0xd8, 0xb7, 0xd6, 0xa4, 0xdb,
|
||||
0x01, 0x11, 0x75, 0x3c, 0xa4, 0x3b, 0x99, 0x5a,
|
||||
0xa4, 0x34, 0xc1, 0x74, 0xc9, 0x38, 0x91, 0xff,
|
||||
0xf3, 0x2a, 0xc0, 0xcb, 0x11, 0xb1, 0x32, 0xa5,
|
||||
0x96, 0x0e, 0x16, 0xc6, 0xcd, 0xc8, 0xce, 0x62,
|
||||
0xa9, 0x05, 0x1c, 0x06, 0x60, 0x4d, 0x70, 0x74,
|
||||
0xb7, 0x80, 0x67, 0x4d, 0xda, 0xcd, 0xd4, 0xad,
|
||||
0xcb, 0x5b, 0x69, 0xfd, 0x46, 0x49, 0x24, 0xa3,
|
||||
0xc3, 0x8d, 0x92, 0x92, 0x53, 0x24, 0x8e, 0xa2,
|
||||
0xe1, 0x39, 0x67, 0x1e, 0x11, 0xe0, 0x29, 0xe0,
|
||||
0xfd, 0xce, 0xfd, 0xa9, 0x6f, 0xd5, 0xee, 0xbd,
|
||||
0x74, 0xe5, 0x0f, 0x19, 0x7d, 0x9b, 0xd2, 0x2e,
|
||||
0xff, 0xf3, 0x38, 0xc0, 0xc0, 0x13, 0x09, 0x9e,
|
||||
0x9b, 0x5e, 0x1c, 0xc6, 0xee, 0x99, 0xff, 0x42,
|
||||
0x89, 0x0a, 0x3c, 0x0c, 0xa7, 0x56, 0x9c, 0x1c,
|
||||
0x0f, 0xd1, 0x6b, 0x1d, 0x0f, 0x89, 0x26, 0xcb,
|
||||
0x70, 0x45, 0xcd, 0x39, 0x84, 0x82, 0xc2, 0xa1,
|
||||
0x06, 0x5a, 0x1b, 0x0d, 0xb5, 0xc4, 0x0b, 0x15,
|
||||
0xff, 0xdd, 0x68, 0xbf, 0x48, 0xaa, 0xaa, 0x69,
|
||||
0xb6, 0xdb, 0xa8, 0xd6, 0xba, 0x5e, 0x86, 0x86,
|
||||
0x56, 0x24, 0xc8, 0x99, 0x98, 0xd1, 0x84, 0x03,
|
||||
0x5d, 0x1d, 0xaf, 0xa0, 0x7d, 0x34, 0xc8, 0xd2,
|
||||
0xd1, 0xaa, 0x0e, 0xba, 0x13, 0xee, 0xe8, 0x31,
|
||||
0x79, 0x8c, 0xcf, 0x1a, 0x24, 0x43, 0x43, 0xb7,
|
||||
0x89, 0xb7, 0xdd, 0x33, 0x4d, 0x85, 0xbd, 0xe7,
|
||||
0xfc, 0x4e, 0xbf, 0x4d, 0xff, 0xf3, 0x2a, 0xc0,
|
||||
0xd2, 0x13, 0x81, 0x86, 0x93, 0x86, 0x1b, 0xca,
|
||||
0xd0, 0xed, 0x97, 0x54, 0x14, 0x43, 0x05, 0xc9,
|
||||
0x04, 0xc1, 0xb5, 0xa6, 0x31, 0x26, 0xe0, 0xa7,
|
||||
0x77, 0xe3, 0xdc, 0x79, 0x17, 0xb2, 0xb0, 0xf0,
|
||||
0x2b, 0x52, 0x74, 0x04, 0xd2, 0x9d, 0x7a, 0xf9,
|
||||
0xa5, 0xd7, 0x7b, 0x8d, 0xff, 0x3a, 0x86, 0xca,
|
||||
0x06, 0x53, 0x5f, 0x33, 0xdf, 0x76, 0xff, 0x2b,
|
||||
0x33, 0xea, 0xb8, 0x34, 0x55, 0x0c, 0x68, 0x3e,
|
||||
0x4c, 0xca, 0x08, 0xc7, 0xae, 0xff, 0xf3, 0x38,
|
||||
0xc0, 0xc0, 0x13, 0x29, 0x5e, 0x97, 0x5e, 0x1b,
|
||||
0xc6, 0xd2, 0x57, 0x26, 0x8c, 0xbe, 0x2c, 0x80,
|
||||
0x22, 0x05, 0xe4, 0x45, 0x10, 0x04, 0x24, 0x01,
|
||||
0xdc, 0x92, 0x24, 0x73, 0x45, 0xe6, 0x3c, 0xcc,
|
||||
0x6b, 0xca, 0x5c, 0x33, 0x31, 0x94, 0xd5, 0x95,
|
||||
0x6b, 0x65, 0xf5, 0x09, 0xda, 0x91, 0xcc, 0x20,
|
||||
0xbe, 0xef, 0xad, 0x85, 0x01, 0x02, 0x1c, 0xc1,
|
||||
0x00, 0xf8, 0xb6, 0xa5, 0x10, 0x6b, 0xfe, 0xfe,
|
||||
0x04, 0x24, 0xd0, 0x9b, 0x5d, 0x55, 0x56, 0x95,
|
||||
0x57, 0x6d, 0x55, 0x54, 0x39, 0x01, 0x10, 0x01,
|
||||
0x05, 0xa9, 0x99, 0x98, 0x58, 0xe0, 0x93, 0xc3,
|
||||
0xb6, 0x58, 0xa0, 0x68, 0xeb, 0xca, 0xb8, 0xa8,
|
||||
0x2a, 0x0a, 0x9d, 0x54, 0x88, 0x2a, 0x0a, 0x89,
|
||||
0x81, 0xff, 0xf3, 0x2a, 0xc0, 0xd2, 0x13, 0x21,
|
||||
0x42, 0xa7, 0x86, 0x1c, 0x8c, 0xee, 0xa0, 0x69,
|
||||
0xe5, 0x8b, 0x3d, 0xde, 0x78, 0xb7, 0xf0, 0xee,
|
||||
0x47, 0xc9, 0x5c, 0x35, 0xc9, 0xca, 0x9d, 0x59,
|
||||
0xdf, 0xf8, 0x88, 0x01, 0x68, 0x84, 0x5a, 0xab,
|
||||
0x51, 0x33, 0xe5, 0x12, 0xe0, 0xef, 0xa9, 0xff,
|
||||
0xff, 0xfd, 0x4b, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xf3, 0x38, 0xc0, 0xc1, 0x15,
|
||||
0x69, 0xce, 0x88, 0xd6, 0x1b, 0xc6, 0xca, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3,
|
||||
0x2a, 0xc0, 0xca, 0x10, 0xf0, 0x92, 0x7e, 0x36,
|
||||
0x08, 0x50, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf3, 0x38, 0xc0, 0xc2, 0x08, 0x80, 0x76, 0x35,
|
||||
0x88, 0x00, 0xc4, 0x84, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xf3, 0x2a, 0xc0, 0xff,
|
||||
0x0f, 0x00, 0x02, 0x5c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xf3, 0x38, 0xc0,
|
||||
0xff, 0x17, 0xc0, 0x02, 0x5c, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xf3, 0x2a, 0xc0, 0xff, 0x0f, 0x00, 0x02,
|
||||
0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00
|
||||
};
|
||||
|
||||
const uint8_t disconnect_mp3[] = {
|
||||
0xff, 0xf3, 0x2a, 0xc0, 0x00, 0x0c, 0xd0, 0x02,
|
||||
0x3e, 0x5f, 0x40, 0x00, 0x02, 0x96, 0xdd, 0xae,
|
||||
0xd1, 0x14, 0x24, 0xb7, 0x00, 0x18, 0x2e, 0x1f,
|
||||
0x10, 0x14, 0x0c, 0x02, 0x00, 0x80, 0xd0, 0x42,
|
||||
0xf1, 0x03, 0x94, 0x71, 0xb0, 0xfa, 0xb9, 0x78,
|
||||
0x80, 0xe0, 0x20, 0xb0, 0xff, 0xff, 0xcb, 0xbc,
|
||||
0x3f, 0xf8, 0x81, 0xc0, 0x87, 0xf9, 0xfc, 0x3e,
|
||||
0x5c, 0xff, 0xf2, 0x8e, 0xff, 0xff, 0x29, 0x88,
|
||||
0x00, 0x75, 0x56, 0x58, 0x57, 0x96, 0x68, 0x35,
|
||||
0x70, 0xff, 0xf3, 0x38, 0xc0, 0x08, 0x11, 0x89,
|
||||
0x12, 0xdb, 0x1f, 0x81, 0x39, 0x02, 0x02, 0x00,
|
||||
0x29, 0xdc, 0xb2, 0xf9, 0xb8, 0x00, 0xe6, 0x64,
|
||||
0xe3, 0x76, 0x21, 0xb0, 0x09, 0x84, 0xc5, 0x79,
|
||||
0xa6, 0x4d, 0x6e, 0x79, 0xac, 0x50, 0xda, 0xa7,
|
||||
0xa3, 0x7a, 0xf5, 0x3c, 0x48, 0x57, 0xe2, 0x59,
|
||||
0x9e, 0x0a, 0xae, 0x08, 0x6f, 0x2b, 0x60, 0x53,
|
||||
0x11, 0xbe, 0x52, 0xaa, 0xbd, 0x50, 0xc4, 0xbf,
|
||||
0x1f, 0xbe, 0x2d, 0x43, 0x14, 0xd9, 0x0f, 0xd2,
|
||||
0xd5, 0xfd, 0x39, 0x15, 0x00, 0x32, 0x35, 0x55,
|
||||
0x67, 0x87, 0x79, 0x66, 0x62, 0x23, 0x00, 0x6b,
|
||||
0xe5, 0x9b, 0x6d, 0xb0, 0x02, 0x13, 0x60, 0x08,
|
||||
0xcd, 0x90, 0xea, 0x40, 0x18, 0x51, 0x88, 0x2c,
|
||||
0x8a, 0x66, 0xf4, 0xba, 0x22, 0xff, 0xf3, 0x2a,
|
||||
0xc0, 0x20, 0x11, 0xd9, 0x12, 0xbf, 0x1f, 0x81,
|
||||
0x50, 0x02, 0x9c, 0xc6, 0x72, 0xa7, 0x75, 0x24,
|
||||
0xea, 0xc1, 0x24, 0x37, 0x6e, 0x2a, 0x07, 0xfe,
|
||||
0x25, 0x0a, 0x71, 0x63, 0x6e, 0x23, 0xcc, 0x8a,
|
||||
0xfa, 0x3a, 0x3c, 0x6d, 0x14, 0xaf, 0xce, 0xed,
|
||||
0x2c, 0x96, 0x76, 0xe9, 0x57, 0x3b, 0xbd, 0x9e,
|
||||
0x49, 0x20, 0x23, 0x33, 0x34, 0x68, 0x85, 0x88,
|
||||
0x03, 0x40, 0x00, 0x00, 0x29, 0xd4, 0xcf, 0x76,
|
||||
0xd8, 0x00, 0x62, 0x94, 0x60, 0xaa, 0xff, 0xf3,
|
||||
0x38, 0xc0, 0x14, 0x10, 0xe9, 0x0e, 0xe3, 0x1f,
|
||||
0x81, 0x39, 0x02, 0xb2, 0x0d, 0xdd, 0x0c, 0x53,
|
||||
0xd5, 0x0e, 0x4e, 0x3f, 0xb3, 0x67, 0x0f, 0x03,
|
||||
0xf1, 0x7b, 0x99, 0x1d, 0x06, 0xf5, 0x0d, 0x72,
|
||||
0x84, 0xbd, 0x1f, 0xca, 0x6a, 0x74, 0xa2, 0x8f,
|
||||
0x2a, 0xe2, 0x39, 0xcf, 0x2c, 0x9e, 0xa7, 0xad,
|
||||
0xf2, 0xfd, 0xa5, 0x6d, 0x5c, 0x97, 0xf3, 0x9f,
|
||||
0x92, 0xfc, 0xa0, 0x8e, 0x0c, 0x21, 0x88, 0x44,
|
||||
0x87, 0x1d, 0x46, 0xcc, 0xd1, 0x19, 0x2e, 0x75,
|
||||
0xf3, 0x2b, 0x01, 0x97, 0xaa, 0x31, 0xf0, 0x5c,
|
||||
0x01, 0x82, 0x52, 0x73, 0x45, 0xe4, 0x45, 0xd2,
|
||||
0xdf, 0xe7, 0x0d, 0xc9, 0x7f, 0x4f, 0xba, 0x93,
|
||||
0x31, 0x42, 0x66, 0x76, 0xf8, 0x0d, 0x8f, 0xfc,
|
||||
0xe7, 0x1a, 0xff, 0xf3, 0x2a, 0xc0, 0x2f, 0x0d,
|
||||
0x18, 0xee, 0xdb, 0xbf, 0xc1, 0x50, 0x02, 0x2a,
|
||||
0x1c, 0x7f, 0x50, 0x0d, 0x20, 0x25, 0x3b, 0xbd,
|
||||
0x44, 0x10, 0x22, 0x6a, 0x11, 0x3e, 0x63, 0x29,
|
||||
0x4c, 0xbb, 0xb9, 0x58, 0xae, 0x49, 0x65, 0x2d,
|
||||
0x72, 0xd4, 0x99, 0x47, 0xa7, 0x97, 0x91, 0xc6,
|
||||
0xb3, 0xb1, 0x2e, 0x50, 0xce, 0x27, 0xdf, 0xfe,
|
||||
0x74, 0x4d, 0x51, 0xff, 0xff, 0xff, 0xd1, 0xff,
|
||||
0x57, 0xff, 0xf4, 0xb3, 0x06, 0xff, 0xfb, 0x7f,
|
||||
0xff, 0xfd, 0x65, 0xff, 0xf3, 0x38, 0xc0, 0x36,
|
||||
0x0e, 0x82, 0x6a, 0xb7, 0xb6, 0x2e, 0x5b, 0x02,
|
||||
0x40, 0x4a, 0x8a, 0x4a, 0x10, 0x05, 0x88, 0xc9,
|
||||
0x92, 0x9f, 0x94, 0xe7, 0xf6, 0xd1, 0x4d, 0x76,
|
||||
0x4f, 0xa7, 0x5b, 0xac, 0xbe, 0x16, 0x48, 0x00,
|
||||
0x60, 0xa8, 0x13, 0xe6, 0x08, 0xd6, 0xc8, 0x8a,
|
||||
0x29, 0x2d, 0xa8, 0x51, 0x7f, 0xfe, 0x79, 0xff,
|
||||
0xfd, 0xd0, 0x76, 0x5b, 0xb2, 0x6a, 0x65, 0xe8,
|
||||
0x2e, 0x82, 0xec, 0xab, 0xff, 0xfe, 0xe6, 0x69,
|
||||
0x11, 0x43, 0x12, 0xd8, 0xca, 0x0e, 0x06, 0x4f,
|
||||
0xff, 0x87, 0x60, 0x22, 0x00, 0xcd, 0xa2, 0x10,
|
||||
0x14, 0x24, 0x62, 0x4c, 0xd9, 0x49, 0x37, 0xe9,
|
||||
0x2d, 0x04, 0xa8, 0xd4, 0x8a, 0x7a, 0x24, 0xf9,
|
||||
0x24, 0x17, 0xe8, 0x00, 0xda, 0xba, 0x8c, 0xff,
|
||||
0xf3, 0x2a, 0xc0, 0x5b, 0x0f, 0xa2, 0x66, 0xd3,
|
||||
0xdc, 0x80, 0x05, 0xe2, 0x30, 0xde, 0x88, 0x45,
|
||||
0x22, 0x46, 0x09, 0xfd, 0x2f, 0xfd, 0x15, 0x92,
|
||||
0x49, 0x7f, 0xff, 0xff, 0xcc, 0x8c, 0x7f, 0xea,
|
||||
0x7f, 0xff, 0x5a, 0x29, 0x13, 0xc2, 0x98, 0x04,
|
||||
0x78, 0xf2, 0x87, 0xff, 0x80, 0x27, 0x58, 0x23,
|
||||
0x0a, 0xce, 0x83, 0x11, 0x26, 0x04, 0x62, 0x4d,
|
||||
0x5d, 0x95, 0xe8, 0xad, 0x94, 0xa6, 0x30, 0xb5,
|
||||
0x49, 0x9c, 0xa8, 0xcc, 0xb4, 0x5c, 0x14, 0x98,
|
||||
0xff, 0xf3, 0x38, 0xc0, 0x58, 0x0f, 0xaa, 0x66,
|
||||
0xb7, 0xe6, 0x88, 0x0b, 0xe0, 0x0a, 0x66, 0x1e,
|
||||
0xd9, 0xeb, 0x33, 0x62, 0x54, 0x00, 0x0c, 0x99,
|
||||
0xa0, 0x89, 0x02, 0x17, 0x12, 0x6a, 0xfd, 0xac,
|
||||
0x93, 0x0c, 0xe2, 0x23, 0x9b, 0xff, 0x7f, 0xff,
|
||||
0xd4, 0xe0, 0x6e, 0x01, 0xb0, 0xb6, 0xff, 0xff,
|
||||
0xff, 0xff, 0xd2, 0x1f, 0x92, 0x20, 0x5d, 0xa9,
|
||||
0x00, 0xd7, 0x41, 0x50, 0x14, 0x68, 0xdf, 0xbb,
|
||||
0x3a, 0x94, 0xea, 0xaa, 0x8a, 0x48, 0x6e, 0x4a,
|
||||
0x89, 0xc8, 0x0a, 0x90, 0x53, 0x0d, 0x52, 0xa9,
|
||||
0x6c, 0x91, 0xc0, 0x0c, 0xc4, 0x24, 0x52, 0x1f,
|
||||
0xc2, 0xfc, 0xff, 0x7a, 0xab, 0x4c, 0x7e, 0x1e,
|
||||
0x25, 0x8b, 0xff, 0xff, 0xff, 0x59, 0x47, 0xff,
|
||||
0xff, 0xff, 0x85, 0x10, 0xff, 0xf3, 0x2a, 0xc0,
|
||||
0x78, 0x10, 0x42, 0x66, 0xaf, 0xe6, 0xa0, 0x1b,
|
||||
0x64, 0x29, 0x45, 0x9f, 0xff, 0x46, 0xff, 0xff,
|
||||
0x19, 0x2f, 0xf5, 0x7a, 0x00, 0x22, 0x0c, 0xdd,
|
||||
0xa3, 0x11, 0x19, 0x75, 0x82, 0xa8, 0x93, 0x6d,
|
||||
0xfa, 0xd9, 0x34, 0x99, 0x9d, 0x9f, 0x41, 0x3a,
|
||||
0xce, 0x17, 0x88, 0x88, 0x7e, 0x20, 0x5d, 0x25,
|
||||
0x57, 0xbb, 0x25, 0x48, 0x35, 0x11, 0xd8, 0xb8,
|
||||
0xd5, 0x10, 0x21, 0x69, 0xfb, 0x2b, 0x52, 0xeb,
|
||||
0x19, 0x23, 0x53, 0x6f, 0xff, 0xff, 0xf3, 0x38,
|
||||
0xc0, 0x73, 0x10, 0x92, 0xaa, 0xae, 0x56, 0x68,
|
||||
0x05, 0xe2, 0xea, 0x57, 0x5f, 0x95, 0xbf, 0xf6,
|
||||
0xff, 0xfd, 0x6b, 0x38, 0x0d, 0xa2, 0x6e, 0xaf,
|
||||
0xfe, 0xa1, 0x00, 0x46, 0x00, 0xbf, 0xa4, 0x11,
|
||||
0x3b, 0xbe, 0xa3, 0x1d, 0x2e, 0xad, 0x6c, 0xdf,
|
||||
0x9c, 0xd3, 0x52, 0xba, 0xf6, 0x1d, 0xc6, 0xc6,
|
||||
0x00, 0x99, 0x77, 0xe8, 0xac, 0xa8, 0x20, 0x05,
|
||||
0xab, 0xa8, 0xa8, 0x22, 0xa5, 0x17, 0x7b, 0xf4,
|
||||
0x66, 0xcc, 0x34, 0x8c, 0x09, 0xaa, 0x2a, 0xff,
|
||||
0xee, 0xcc, 0xa5, 0xf5, 0xad, 0x35, 0x2c, 0x95,
|
||||
0xb7, 0xff, 0xff, 0xb2, 0x91, 0x4a, 0x27, 0xc0,
|
||||
0x06, 0x81, 0xe5, 0xfe, 0xe8, 0xf3, 0x44, 0xb0,
|
||||
0xdc, 0xe0, 0x45, 0x0c, 0xa0, 0xa4, 0x01, 0x2b,
|
||||
0xbe, 0xff, 0xf3, 0x2a, 0xc0, 0x8f, 0x10, 0x22,
|
||||
0x62, 0xab, 0xe6, 0x98, 0x0b, 0xe0, 0xc3, 0x2c,
|
||||
0xc3, 0x4d, 0xfa, 0x2a, 0x5a, 0xbf, 0xb2, 0x5a,
|
||||
0x8c, 0x8b, 0x46, 0x80, 0x7c, 0x7f, 0x39, 0x30,
|
||||
0x00, 0x26, 0xc8, 0x06, 0xcb, 0x2a, 0x14, 0x8d,
|
||||
0xbd, 0xaf, 0x5b, 0x4c, 0x46, 0x10, 0xd6, 0xba,
|
||||
0xbe, 0xb5, 0x76, 0x7b, 0x54, 0xfb, 0x5c, 0xa4,
|
||||
0xde, 0xbf, 0xff, 0xfa, 0x06, 0x6c, 0xb1, 0x3f,
|
||||
0x00, 0x79, 0x16, 0x9f, 0xfe, 0x88, 0x56, 0x12,
|
||||
0x13, 0x00, 0xff, 0xf3, 0x38, 0xc0, 0x8a, 0x11,
|
||||
0x9a, 0x66, 0xa7, 0xe6, 0x68, 0x0f, 0xe1, 0x34,
|
||||
0x00, 0xbe, 0x93, 0x00, 0x29, 0xb6, 0xdb, 0x47,
|
||||
0x2e, 0x97, 0xf5, 0x77, 0xf4, 0xf5, 0x14, 0xc6,
|
||||
0x50, 0x51, 0x09, 0xa9, 0xb7, 0x98, 0xd2, 0x07,
|
||||
0xd4, 0xeb, 0x33, 0x14, 0xd1, 0xf4, 0x4f, 0x95,
|
||||
0x09, 0xd1, 0x52, 0x9f, 0x3b, 0x66, 0x9b, 0x7b,
|
||||
0xdb, 0x9a, 0x1d, 0x63, 0x7a, 0x53, 0xeb, 0xec,
|
||||
0xba, 0x90, 0x2a, 0x32, 0x1c, 0xe1, 0x5e, 0x04,
|
||||
0xd0, 0x8c, 0x8f, 0xfd, 0xff, 0xdb, 0xeb, 0x7f,
|
||||
0xf5, 0x92, 0x2a, 0x02, 0x44, 0x0b, 0xbe, 0x84,
|
||||
0x11, 0x3b, 0xb7, 0xc3, 0x9c, 0x2b, 0x9f, 0xb7,
|
||||
0xa3, 0x75, 0x36, 0xfe, 0xaa, 0x8e, 0xa8, 0x8b,
|
||||
0x11, 0x60, 0x5c, 0x64, 0x92, 0x3c, 0xff, 0xf3,
|
||||
0x2a, 0xc0, 0xa2, 0x10, 0x8a, 0x66, 0xa3, 0xe6,
|
||||
0x68, 0x1b, 0xe1, 0xe4, 0xe0, 0x6d, 0xc6, 0xce,
|
||||
0x70, 0x7c, 0x8b, 0x31, 0x1e, 0xcd, 0xf9, 0xd2,
|
||||
0x75, 0xdd, 0xfd, 0x5b, 0x6b, 0x7d, 0xfb, 0xfa,
|
||||
0xcd, 0xde, 0xab, 0x55, 0xdb, 0xb7, 0xeb, 0x9a,
|
||||
0xa4, 0x99, 0xd2, 0x28, 0x14, 0x38, 0x86, 0x2d,
|
||||
0xb6, 0xfd, 0xca, 0x03, 0xd0, 0xca, 0x50, 0x43,
|
||||
0x0b, 0xbc, 0xa3, 0x21, 0x29, 0x76, 0xb7, 0x58,
|
||||
0x89, 0xe5, 0xf0, 0xd3, 0x05, 0xab, 0xb0, 0xff,
|
||||
0xf3, 0x38, 0xc0, 0x9b, 0x11, 0x42, 0x66, 0x9b,
|
||||
0xe6, 0x69, 0xdb, 0x4d, 0xd0, 0x4c, 0x79, 0x16,
|
||||
0xd0, 0x8e, 0x81, 0x8d, 0x13, 0x6a, 0xaa, 0x75,
|
||||
0xe1, 0xe0, 0x41, 0xd3, 0x44, 0x31, 0x89, 0xa7,
|
||||
0xbf, 0xec, 0x26, 0xd3, 0x96, 0xf5, 0x7d, 0x7a,
|
||||
0xae, 0xcf, 0xf5, 0x1e, 0xba, 0xd7, 0xf5, 0x2f,
|
||||
0xa3, 0xfd, 0x66, 0xaa, 0x3e, 0x3e, 0x82, 0xfd,
|
||||
0x03, 0x5b, 0x0d, 0x84, 0xb9, 0xb2, 0xbf, 0xff,
|
||||
0xfd, 0x07, 0x7f, 0xd4, 0xa2, 0xa8, 0xb6, 0xb8,
|
||||
0x33, 0x00, 0x9b, 0xa3, 0x11, 0x49, 0x75, 0xf7,
|
||||
0x38, 0x8c, 0xb7, 0xfd, 0x6a, 0x46, 0x41, 0xac,
|
||||
0xe2, 0xc6, 0x44, 0x2d, 0xa8, 0x3e, 0x24, 0xb3,
|
||||
0xb6, 0x72, 0x70, 0x2d, 0x18, 0x84, 0x76, 0x1a,
|
||||
0x86, 0x4a, 0x6f, 0xff, 0xf3, 0x2a, 0xc0, 0xb5,
|
||||
0x11, 0x62, 0x66, 0x97, 0xe6, 0x98, 0x0f, 0xe1,
|
||||
0xfe, 0x39, 0xc6, 0xad, 0xff, 0xfa, 0x34, 0xfd,
|
||||
0x77, 0x99, 0xff, 0xef, 0xdf, 0xf4, 0x58, 0xd4,
|
||||
0xba, 0x78, 0x5a, 0x45, 0x04, 0x1e, 0xc0, 0xe4,
|
||||
0x96, 0x9d, 0xd5, 0xff, 0xfd, 0xbe, 0x65, 0xff,
|
||||
0x2f, 0x90, 0x52, 0xa8, 0xd0, 0x48, 0x0a, 0x23,
|
||||
0x01, 0x40, 0xdc, 0x0e, 0x00, 0x81, 0x01, 0x3c,
|
||||
0xb6, 0xff, 0x43, 0xf5, 0x26, 0xc9, 0x97, 0x03,
|
||||
0x2d, 0x0c, 0xb2, 0x21, 0xff, 0xf3, 0x38, 0xc0,
|
||||
0xab, 0x12, 0xea, 0x6a, 0x87, 0xe6, 0x48, 0x64,
|
||||
0x14, 0x65, 0x2a, 0x5f, 0x5d, 0x10, 0x6f, 0x29,
|
||||
0x56, 0x88, 0xfc, 0x27, 0x37, 0xf4, 0xd1, 0xd1,
|
||||
0x74, 0x88, 0x68, 0x82, 0x24, 0x8f, 0xff, 0xf4,
|
||||
0xbf, 0xa9, 0xe6, 0x8f, 0xf5, 0x57, 0xf5, 0x69,
|
||||
0x6e, 0xa9, 0x68, 0xe9, 0x1c, 0x39, 0x40, 0xd0,
|
||||
0xa0, 0x6c, 0x88, 0xe6, 0x9a, 0x9a, 0x1a, 0x2f,
|
||||
0xfc, 0x60, 0xe7, 0x7f, 0xe8, 0x66, 0xa7, 0x72,
|
||||
0x3d, 0x00, 0x60, 0x0b, 0xe5, 0xd4, 0x5b, 0x85,
|
||||
0x30, 0xac, 0xbf, 0xff, 0xef, 0x8d, 0x67, 0xd5,
|
||||
0x59, 0x80, 0xca, 0x59, 0x45, 0x92, 0x59, 0xd1,
|
||||
0x5e, 0xf2, 0x4a, 0xf2, 0xb8, 0xc2, 0xa2, 0x3c,
|
||||
0xf0, 0xa2, 0x4d, 0xec, 0xb9, 0x45, 0x8c, 0xe2,
|
||||
0xff, 0xf3, 0x2a, 0xc0, 0xbe, 0x11, 0xe2, 0x66,
|
||||
0x83, 0xe6, 0x30, 0x66, 0x15, 0x75, 0xf0, 0xfd,
|
||||
0xd9, 0xfa, 0xd5, 0x9f, 0xff, 0xf5, 0x37, 0xfd,
|
||||
0xe7, 0x1d, 0xff, 0x64, 0xfa, 0xb6, 0x87, 0x33,
|
||||
0x9a, 0x25, 0x00, 0x08, 0x16, 0x80, 0xb8, 0x7a,
|
||||
0x74, 0xef, 0xff, 0xff, 0xff, 0xe3, 0xe1, 0xf1,
|
||||
0xd3, 0x00, 0x17, 0xff, 0xfa, 0x45, 0xcc, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xf3, 0x38, 0xc0, 0xb2, 0x13, 0xda,
|
||||
0x66, 0x76, 0x5e, 0x98, 0x05, 0xe2, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf3, 0x2a,
|
||||
0xc0, 0xc1, 0x12, 0x8a, 0x66, 0x57, 0x8e, 0x16,
|
||||
0x14, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf3,
|
||||
0x38, 0xc0, 0xb2, 0x04, 0x68, 0x06, 0x30, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
50
sdk/app/audio_media_ctrl/wave/wave_code.h
Normal file
50
sdk/app/audio_media_ctrl/wave/wave_code.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef _WAVE_CODE_H_
|
||||
#define _WAVE_CODE_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "audio_code_ctrl.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define WAVE_CODE_MALLOC av_psram_malloc
|
||||
#define WAVE_CODE_ZALLOC av_psram_zalloc
|
||||
#define WAVE_CODE_FREE av_psram_free
|
||||
#else
|
||||
#define WAVE_CODE_MALLOC av_malloc
|
||||
#define WAVE_CODE_ZALLOC av_zalloc
|
||||
#define WAVE_CODE_FREE av_free
|
||||
#endif
|
||||
|
||||
#define WAVE_DEBUG(fmt, args...) //os_printf(fmt, ##args)
|
||||
#define WAVE_INFO os_printf
|
||||
|
||||
typedef struct _riff_chunk {
|
||||
uint8_t ChunkID[4];
|
||||
uint32_t ChunkSize;
|
||||
uint8_t Format[4];
|
||||
} TYPE_RIFF_CHUNK;
|
||||
typedef struct _fmt_chunk {
|
||||
uint8_t FmtID[4];
|
||||
uint32_t FmtSize;
|
||||
uint16_t FmtTag;
|
||||
uint16_t FmtChannels;
|
||||
uint32_t SampleRate;
|
||||
uint32_t ByteRate;
|
||||
uint16_t BlockAlign;
|
||||
uint16_t BitsPerSample;
|
||||
} TYPE_FMT_CHUNK;
|
||||
typedef struct _data_chunk {
|
||||
uint8_t DataID[4];
|
||||
uint32_t DataSize;
|
||||
} TYPE_DATA_CHUNK;
|
||||
typedef struct _wave_head {
|
||||
TYPE_RIFF_CHUNK riff_chunk;
|
||||
TYPE_FMT_CHUNK fmt_chunk;
|
||||
TYPE_DATA_CHUNK data_chunk;
|
||||
} TYPE_WAVE_HEAD;
|
||||
|
||||
struct msi *wave_encode_init(char *filename, uint32_t samplerate, AUENC_INIT *auenc_init);
|
||||
struct msi *wave_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init);
|
||||
|
||||
#endif
|
||||
459
sdk/app/audio_media_ctrl/wave/wave_decode.c
Normal file
459
sdk/app/audio_media_ctrl/wave/wave_decode.c
Normal file
@@ -0,0 +1,459 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "autpc_msi/autpc_msi.h"
|
||||
#include "osal_file.h"
|
||||
#include "wave_code.h"
|
||||
|
||||
#define BUFF_SIZE 1024
|
||||
#define MAX_WAVE_DECODE_TXBUF 4
|
||||
|
||||
struct wave_decode_struct {
|
||||
AUDIO_TRACK audio_track;
|
||||
struct fbpool tx_pool;
|
||||
struct os_event event;
|
||||
struct msi *msi;
|
||||
struct msi *autpc_msi;
|
||||
char *msi_name;
|
||||
void *task_hdl;
|
||||
void *wave_fp;
|
||||
uint8_t loop_mode;
|
||||
uint8_t direct_to_dac;
|
||||
uint8_t use_tpc;
|
||||
uint8_t speed;
|
||||
uint8_t pitch;
|
||||
uint8_t destroy_self;
|
||||
uint8_t get_wave_head;
|
||||
uint8_t next_status;
|
||||
uint8_t current_status;
|
||||
uint8_t buf[BUFF_SIZE];
|
||||
uint32_t buf_size;
|
||||
TYPE_WAVE_HEAD wave_head;
|
||||
};
|
||||
|
||||
static void get_wave_head(struct wave_decode_struct *s)
|
||||
{
|
||||
int32_t read_len = 0;
|
||||
uint32_t offset = 0;
|
||||
uint32_t head_seek = 0;
|
||||
|
||||
read_len = osal_fread(s->buf, 512, 1, s->wave_fp);
|
||||
if(read_len <= 0) {
|
||||
WAVE_INFO("wave read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
|
||||
return;
|
||||
}
|
||||
s->buf_size = read_len;
|
||||
os_memcpy((uint8_t*)(&(s->wave_head)), s->buf, sizeof(TYPE_RIFF_CHUNK)+sizeof(TYPE_FMT_CHUNK));
|
||||
if(os_strncmp(&(s->wave_head.riff_chunk), "RIFF", 4) != 0) {
|
||||
WAVE_INFO("wave head err!\n");
|
||||
return;
|
||||
}
|
||||
offset = sizeof(TYPE_RIFF_CHUNK)+sizeof(TYPE_FMT_CHUNK);
|
||||
while(os_strncmp(s->buf+offset, "data", 4) != 0) {
|
||||
offset++;
|
||||
if(offset >= s->buf_size-(sizeof(TYPE_DATA_CHUNK)-1)) {
|
||||
os_memcpy(s->buf, s->buf+s->buf_size+(sizeof(TYPE_DATA_CHUNK)-1), sizeof(TYPE_DATA_CHUNK)-1);
|
||||
head_seek += read_len;
|
||||
read_len = osal_fread(s->buf+(sizeof(TYPE_DATA_CHUNK)-1), 512, 1, s->wave_fp);
|
||||
if(read_len <= 0) {
|
||||
WAVE_INFO("wave read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
|
||||
return;
|
||||
}
|
||||
s->buf_size = read_len + (sizeof(TYPE_DATA_CHUNK)-1);
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
head_seek += (offset+sizeof(TYPE_DATA_CHUNK));
|
||||
os_memcpy((uint8_t*)(&(s->wave_head.data_chunk)), s->buf+offset, sizeof(TYPE_DATA_CHUNK));
|
||||
osal_fseek(s->wave_fp, head_seek);
|
||||
s->get_wave_head = 1;
|
||||
}
|
||||
|
||||
static void wave_decode(struct wave_decode_struct *s)
|
||||
{
|
||||
int16_t *data = NULL;
|
||||
int32_t ret = 0;
|
||||
int32_t read_len = 0;
|
||||
int32_t audio_temp = 0;
|
||||
uint32_t once_read_size = 0;
|
||||
uint32_t read_total_size = 0;
|
||||
uint32_t interval_time = 0;
|
||||
struct framebuff *frame_buf = NULL;
|
||||
AUDIO_TRACK *audac_fiter_track = NULL;
|
||||
|
||||
if(s->wave_head.fmt_chunk.BitsPerSample == 24) {
|
||||
once_read_size = BUFF_SIZE*8/24; //sample取整
|
||||
once_read_size = once_read_size*3/4; //sample取偶
|
||||
once_read_size *= 4;
|
||||
}
|
||||
else if(s->wave_head.fmt_chunk.BitsPerSample == 16) {
|
||||
once_read_size = BUFF_SIZE;
|
||||
}
|
||||
else if(s->wave_head.fmt_chunk.BitsPerSample == 8) {
|
||||
once_read_size = BUFF_SIZE/2;
|
||||
}
|
||||
while(1) {
|
||||
if(s->next_status == AUCODEC_PAUSE) {
|
||||
if(s->current_status == AUCODEC_RUN) {
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
while(s->next_status == AUCODEC_PAUSE) {
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
break;
|
||||
}
|
||||
s->current_status = AUCODEC_RUN;
|
||||
frame_buf = fbpool_get(&s->tx_pool, 0, s->msi);
|
||||
if(frame_buf) {
|
||||
data = (int16_t*)(frame_buf->data);
|
||||
if(read_total_size >= s->wave_head.data_chunk.DataSize) {
|
||||
goto wave_decode_end;
|
||||
}
|
||||
if((read_total_size+once_read_size) > s->wave_head.data_chunk.DataSize) {
|
||||
read_len = osal_fread((uint8_t*)data, 1, (s->wave_head.data_chunk.DataSize-read_total_size), s->wave_fp);
|
||||
}
|
||||
else
|
||||
read_len = osal_fread((uint8_t*)data, 1, once_read_size, s->wave_fp);
|
||||
if(read_len > 0) {
|
||||
read_total_size += read_len;
|
||||
if(s->wave_head.fmt_chunk.BitsPerSample == 24) {
|
||||
for(uint32_t i=0; i<(read_len/3); i++) {
|
||||
audio_temp = (int32_t)((*((uint8_t*)data+3*i))|(*((uint8_t*)data+3*i+1)<<8)|(*((uint8_t*)data+3*i+2))<<16)&0x00FFFFFF;
|
||||
data[i] = audio_temp>>8;
|
||||
}
|
||||
read_len = read_len*2/3;
|
||||
}
|
||||
else if(s->wave_head.fmt_chunk.BitsPerSample == 8) {
|
||||
os_memcpy(data+read_len/2, data, read_len);
|
||||
for(uint32_t i=0; i<read_len; i++) {
|
||||
data[i] = (int16_t)(*(((uint8_t*)data)+read_len+i)-128)<<8;
|
||||
}
|
||||
read_len = read_len*2;
|
||||
}
|
||||
|
||||
if(s->wave_head.fmt_chunk.FmtChannels == 2) {
|
||||
for(uint32_t i=0; i<(read_len/4); i++) {
|
||||
data[i] = (( ((int32_t)data[2*i]) + data[2*i+1] ) >>1 );
|
||||
}
|
||||
read_len = read_len/2;
|
||||
}
|
||||
frame_buf->len = read_len;
|
||||
frame_buf->mtype = F_AUDIO;
|
||||
frame_buf->stype = FSTYPE_AUDIO_PCM;
|
||||
s->audio_track.samplerate = s->wave_head.fmt_chunk.SampleRate;
|
||||
if(s->use_tpc && !s->autpc_msi) {
|
||||
s->autpc_msi = autpc_msi_init(s->audio_track.samplerate, s->speed, s->pitch, read_len/2, &(s->audio_track));
|
||||
if(s->autpc_msi == NULL) {
|
||||
goto wave_decode_end;
|
||||
}
|
||||
msi_add_output(s->msi, NULL, s->autpc_msi->name);
|
||||
if(s->direct_to_dac) {
|
||||
msi_add_output(s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
}
|
||||
ret = msi_output_fb(s->msi, frame_buf);
|
||||
WAVE_DEBUG("wave decode send framebuff:%p,ret:%d\r\n",frame_buf,ret);
|
||||
msi_cmd("R_AUDAC", MSI_CMD_AUDAC, MSI_AUDAC_GET_FILTER_TRACK, (uint32_t)(&audac_fiter_track));
|
||||
if(s->direct_to_dac && (!s->use_tpc) && (audac_fiter_track != (&(s->audio_track)))) {
|
||||
interval_time = (frame_buf->len>>1)*1000/(s->wave_head.fmt_chunk.SampleRate);
|
||||
os_sleep_ms(interval_time);
|
||||
}
|
||||
frame_buf = NULL;
|
||||
}
|
||||
else if(read_len <= 0 ) {
|
||||
msi_delete_fb(s->msi, frame_buf);
|
||||
frame_buf = NULL;
|
||||
WAVE_INFO("wave read fail,ret:%d,line:%d!\r\n",read_len,__LINE__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
wave_decode_end:
|
||||
msi_output_cmd(s->msi,MSI_CMD_AUTPC,MSI_AUTPC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_END_STREAM,(uint32_t)(&(s->audio_track)));
|
||||
if(frame_buf) {
|
||||
msi_delete_fb(s->msi, frame_buf);
|
||||
frame_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void wave_decode_thread(void *d)
|
||||
{
|
||||
struct wave_decode_struct *s = (struct wave_decode_struct *)d;
|
||||
|
||||
if(s->wave_fp) {
|
||||
get_wave_head(s);
|
||||
if(!s->get_wave_head) {
|
||||
WAVE_INFO("wave head err!\n");
|
||||
goto wave_decode_thread_end;
|
||||
}
|
||||
}
|
||||
|
||||
msi_get(s->msi);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
s->msi->enable = 1;
|
||||
do {
|
||||
osal_fseek(s->wave_fp, sizeof(TYPE_WAVE_HEAD));
|
||||
wave_decode(s);
|
||||
if(s->current_status == AUCODEC_EXIT) {
|
||||
break;
|
||||
}
|
||||
}while(s->loop_mode);
|
||||
|
||||
if(s->direct_to_dac) {
|
||||
s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(s->audio_track)));
|
||||
}
|
||||
|
||||
wave_decode_thread_end:
|
||||
os_event_set(&s->event, coder_exit_event, NULL);
|
||||
|
||||
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
|
||||
s->current_status = AUCODEC_END;
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
|
||||
if(s->next_status != AUCODEC_EXIT)
|
||||
msi_destroy(s->msi);
|
||||
|
||||
msi_put(s->msi);
|
||||
}
|
||||
|
||||
static int32_t wave_decode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct wave_decode_struct *wave_decode_s = (struct wave_decode_struct *)(msi->priv);
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_AUCODER:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(wave_decode_s) {
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUCODER_PAUSE:
|
||||
{
|
||||
if(wave_decode_s->current_status == AUCODEC_RUN) {
|
||||
wave_decode_s->next_status = AUCODEC_PAUSE;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CONTINUE:
|
||||
{
|
||||
if(wave_decode_s->current_status == AUCODEC_PAUSE) {
|
||||
wave_decode_s->next_status = AUCODEC_RUN;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_STATUS:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(wave_decode_s->current_status);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SPEED:
|
||||
{
|
||||
wave_decode_s->speed = (uint8_t)param2;
|
||||
ret = msi_output_cmd(wave_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_SPEED,(uint32_t)(wave_decode_s->speed));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_SPEED:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(wave_decode_s->speed);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_PITCH:
|
||||
{
|
||||
wave_decode_s->pitch = (uint8_t)param2;
|
||||
ret = msi_output_cmd(wave_decode_s->msi,MSI_CMD_AUTPC,MSI_AUTPC_SET_PITCH,(uint32_t)(wave_decode_s->pitch));
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_PITCH:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(wave_decode_s->pitch);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DIRECT_TO_DAC:
|
||||
{
|
||||
uint32_t direct_to_dac = param2;
|
||||
if(direct_to_dac && wave_decode_s->direct_to_dac == 0) {
|
||||
wave_decode_s->direct_to_dac = 1;
|
||||
if(wave_decode_s->use_tpc == 0) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(wave_decode_s->autpc_msi) {
|
||||
msi_add_output(wave_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(wave_decode_s->audio_track)));
|
||||
}
|
||||
else if(wave_decode_s->direct_to_dac == 1) {
|
||||
wave_decode_s->direct_to_dac = 0;
|
||||
if(wave_decode_s->use_tpc == 0) {
|
||||
msi_del_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
else if(wave_decode_s->autpc_msi) {
|
||||
msi_del_output(wave_decode_s->autpc_msi, NULL, "R_AUDAC");
|
||||
}
|
||||
wave_decode_s->audio_track.priority &= 0x3F;
|
||||
msi_cmd("R_AUDAC",MSI_CMD_AUDAC,MSI_AUDAC_SET_FILTER_TRACK,(uint32_t)(&(wave_decode_s->audio_track)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DEINIT:
|
||||
{
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(wave_decode_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
fbpool_put(&wave_decode_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if(wave_decode_s && wave_decode_s->task_hdl) {
|
||||
wave_decode_s->next_status = AUCODEC_EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(wave_decode_s) {
|
||||
if(wave_decode_s->task_hdl) {
|
||||
os_event_wait(&wave_decode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
}
|
||||
for(uint32_t i=0; i<MAX_WAVE_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (wave_decode_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
WAVE_CODE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&wave_decode_s->tx_pool);
|
||||
if(wave_decode_s->event.hdl) {
|
||||
os_event_del(&wave_decode_s->event);
|
||||
}
|
||||
if(wave_decode_s->wave_fp) {
|
||||
osal_fclose(wave_decode_s->wave_fp);
|
||||
wave_decode_s->wave_fp = NULL;
|
||||
}
|
||||
if(wave_decode_s->autpc_msi) {
|
||||
autpc_msi_deinit(wave_decode_s->autpc_msi);
|
||||
wave_decode_s->autpc_msi = NULL;
|
||||
}
|
||||
if(wave_decode_s->msi_name) {
|
||||
WAVE_CODE_FREE(wave_decode_s->msi_name);
|
||||
wave_decode_s->msi_name = NULL;
|
||||
}
|
||||
WAVE_CODE_FREE(wave_decode_s);
|
||||
wave_decode_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *wave_decode_init(char *filename, uint8_t loop_mode, AUDEC_INIT *audec_init)
|
||||
{
|
||||
#if AUDIO_EN
|
||||
char *msi_name = NULL;
|
||||
|
||||
msi_name = (char*)WAVE_CODE_ZALLOC(sizeof(char)*32);
|
||||
if(msi_name == NULL) {
|
||||
os_printf("alloc autpc msi namefail\n");
|
||||
return NULL;
|
||||
}
|
||||
os_snprintf(msi_name, 20, "S_WAVE_DECODE_""%04d", (int)(os_jiffies()));
|
||||
struct msi *msi = msi_new(msi_name, 0, NULL);
|
||||
if(!msi) {
|
||||
WAVE_INFO("create wave decode msi fail!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
struct wave_decode_struct *wave_decode_s = (struct wave_decode_struct *)WAVE_CODE_ZALLOC(sizeof(struct wave_decode_struct));
|
||||
if(!wave_decode_s) {
|
||||
WAVE_INFO("wave_decode_s malloc fail!\r\n");
|
||||
goto wave_decode_init_err;
|
||||
}
|
||||
msi->priv = wave_decode_s;
|
||||
msi->action = (msi_action)wave_decode_msi_action;
|
||||
fbpool_init(&wave_decode_s->tx_pool, MAX_WAVE_DECODE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_WAVE_DECODE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (wave_decode_s->tx_pool.pool)+i;
|
||||
frame_buf->data = (uint8_t*)WAVE_CODE_MALLOC(BUFF_SIZE);
|
||||
if(frame_buf->data == NULL) {
|
||||
WAVE_INFO("wave decode malloc framebuff data fail!\r\n");
|
||||
goto wave_decode_init_err;
|
||||
}
|
||||
frame_buf->priv = &(wave_decode_s->audio_track);
|
||||
}
|
||||
if(filename) {
|
||||
wave_decode_s->wave_fp = osal_fopen((const char*)filename, "rb");
|
||||
if(wave_decode_s->wave_fp == NULL) {
|
||||
WAVE_INFO("open wave file %s fail!\r\n", filename);
|
||||
goto wave_decode_init_err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
WAVE_INFO("wave filename is null!\r\n");
|
||||
goto wave_decode_init_err;
|
||||
}
|
||||
if(os_event_init(&wave_decode_s->event) != RET_OK) {
|
||||
WAVE_INFO("create wave decode event fail!\r\n");
|
||||
goto wave_decode_init_err;
|
||||
}
|
||||
wave_decode_s->msi = msi;
|
||||
wave_decode_s->msi_name = msi_name;
|
||||
wave_decode_s->loop_mode = loop_mode;
|
||||
wave_decode_s->direct_to_dac = audec_init->direct_to_dac;
|
||||
wave_decode_s->use_tpc = audec_init->use_tpc;
|
||||
wave_decode_s->speed = audec_init->speed;
|
||||
wave_decode_s->pitch = audec_init->pitch;
|
||||
wave_decode_s->destroy_self = audec_init->destroy_self;
|
||||
wave_decode_s->audio_track.priority = audec_init->priority;
|
||||
wave_decode_s->audio_track.track_type = audec_init->track_type;
|
||||
wave_decode_s->next_status = AUCODEC_RUN;
|
||||
wave_decode_s->current_status = AUCODEC_RUN;
|
||||
if(audec_init->direct_to_dac && !wave_decode_s->use_tpc) {
|
||||
msi_add_output(msi, NULL, "R_AUDAC");
|
||||
}
|
||||
wave_decode_s->task_hdl = os_task_create("wave_decode_thread", wave_decode_thread, (void*)wave_decode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||||
if(wave_decode_s->task_hdl == NULL) {
|
||||
WAVE_INFO("create wave decode task fail!\r\n");
|
||||
goto wave_decode_init_err;
|
||||
}
|
||||
return msi;
|
||||
|
||||
wave_decode_init_err:
|
||||
msi_destroy(msi);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
256
sdk/app/audio_media_ctrl/wave/wave_encode.c
Normal file
256
sdk/app/audio_media_ctrl/wave/wave_encode.c
Normal file
@@ -0,0 +1,256 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "osal_file.h"
|
||||
#include "wave_code.h"
|
||||
|
||||
#define MAX_WAVE_ENCODE_RXBUF 4
|
||||
|
||||
struct wave_encode_struct {
|
||||
struct os_event event;
|
||||
struct msi *msi;
|
||||
struct msi *src_msi;
|
||||
void *task_hdl;
|
||||
void *wave_fp;
|
||||
uint8_t destroy_self;
|
||||
uint8_t next_status;
|
||||
uint8_t current_status;
|
||||
uint32_t samplerate;
|
||||
uint32_t data_size;
|
||||
TYPE_WAVE_HEAD wave_head;
|
||||
};
|
||||
|
||||
const unsigned char wav_header[] = {
|
||||
'R', 'I', 'F', 'F', // "RIFF" 标志
|
||||
0, 0, 0, 0, // 文件长度
|
||||
'W', 'A', 'V', 'E', // "WAVE" 标志
|
||||
'f', 'm', 't', ' ', // "fmt" 标志
|
||||
16, 0, 0, 0, // 过渡字节(不定)
|
||||
0x01, 0x00, // 格式类别
|
||||
0x01, 0x00, // 声道数
|
||||
0, 0, 0, 0, // 采样率
|
||||
0, 0, 0, 0, // 位速
|
||||
0x01, 0x00, // 一个采样多声道数据块大小
|
||||
0x10, 0x00, // 一个采样占的 bit 数
|
||||
'd', 'a', 't', 'a', // 数据标记符"data "
|
||||
0, 0, 0, 0 // 语音数据的长度,比文件长度小42一般。这个是计算音频播放时长的关键参数~
|
||||
};
|
||||
|
||||
static void wave_encode_thread(void *d)
|
||||
{
|
||||
uint8_t *data = NULL;
|
||||
uint32_t data_len = 0;
|
||||
struct wave_encode_struct *s = (struct wave_encode_struct *)d;
|
||||
struct framebuff *frame_buf = NULL;
|
||||
|
||||
s->msi->enable = 1;
|
||||
msi_get(s->msi);
|
||||
|
||||
while(1)
|
||||
{
|
||||
frame_buf = msi_get_fb(s->msi, 0);
|
||||
if(frame_buf)
|
||||
{
|
||||
if(s->next_status == AUCODEC_PAUSE)
|
||||
s->current_status = AUCODEC_PAUSE;
|
||||
else {
|
||||
s->current_status = AUCODEC_RUN;
|
||||
data = frame_buf->data;
|
||||
data_len = frame_buf->len;
|
||||
osal_fwrite(data, 2, data_len/2, s->wave_fp);
|
||||
s->data_size += data_len;
|
||||
}
|
||||
msi_delete_fb(s->msi, frame_buf);
|
||||
WAVE_DEBUG("wave encode delete framebuff:%p,len:%d,\r\n",frame_buf,frame_buf->len);
|
||||
frame_buf = NULL;
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
|
||||
if(s->next_status == AUCODEC_EXIT) {
|
||||
s->current_status = AUCODEC_EXIT;
|
||||
s->wave_head.riff_chunk.ChunkSize = s->data_size + sizeof(TYPE_WAVE_HEAD) - 8;
|
||||
s->wave_head.fmt_chunk.SampleRate = s->samplerate;
|
||||
s->wave_head.fmt_chunk.ByteRate = s->samplerate*2;
|
||||
s->wave_head.data_chunk.DataSize = s->data_size;
|
||||
osal_fseek(s->wave_fp, 0);
|
||||
osal_fwrite(&(s->wave_head), 1, sizeof(TYPE_WAVE_HEAD), s->wave_fp);
|
||||
goto wave_encode_thread_end;
|
||||
}
|
||||
}
|
||||
wave_encode_thread_end:
|
||||
os_event_set(&s->event, coder_exit_event, NULL);
|
||||
|
||||
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
|
||||
s->current_status = AUCODEC_END;
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
|
||||
if(s->src_msi) {
|
||||
msi_del_output(s->src_msi, NULL, s->msi->name);
|
||||
s->src_msi = NULL;
|
||||
}
|
||||
|
||||
if(s->next_status != AUCODEC_EXIT)
|
||||
msi_destroy(s->msi);
|
||||
|
||||
msi_put(s->msi);
|
||||
}
|
||||
|
||||
static int32_t wave_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct wave_encode_struct *wave_encode_s = (struct wave_encode_struct*)(msi->priv);
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_AUCODER:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(wave_encode_s) {
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUCODER_PAUSE:
|
||||
{
|
||||
if(wave_encode_s->current_status == AUCODEC_RUN) {
|
||||
wave_encode_s->next_status = AUCODEC_PAUSE;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_CONTINUE:
|
||||
{
|
||||
if(wave_encode_s->current_status == AUCODEC_PAUSE) {
|
||||
wave_encode_s->next_status = AUCODEC_RUN;
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_GET_STATUS:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(wave_encode_s->current_status);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_SET_SRCMSI:
|
||||
{
|
||||
if(wave_encode_s->src_msi) {
|
||||
msi_del_output(wave_encode_s->src_msi, NULL, msi->name);
|
||||
}
|
||||
wave_encode_s->src_msi = NULL;
|
||||
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
|
||||
if(ret == RET_OK) {
|
||||
wave_encode_s->src_msi = (struct msi*)param2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUCODER_DEINIT:
|
||||
{
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->mtype == F_AUDIO) {
|
||||
ret = RET_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if(wave_encode_s && wave_encode_s->task_hdl) {
|
||||
wave_encode_s->next_status = AUCODEC_EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(wave_encode_s) {
|
||||
if(wave_encode_s->task_hdl) {
|
||||
os_event_wait(&wave_encode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
|
||||
}
|
||||
if(wave_encode_s->event.hdl) {
|
||||
os_event_del(&wave_encode_s->event);
|
||||
}
|
||||
if(wave_encode_s->wave_fp) {
|
||||
osal_fclose(wave_encode_s->wave_fp);
|
||||
wave_encode_s->wave_fp = NULL;
|
||||
}
|
||||
WAVE_CODE_FREE(wave_encode_s);
|
||||
wave_encode_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *wave_encode_init(char *filename, uint32_t samplerate, AUENC_INIT *auenc_init)
|
||||
{
|
||||
#if AUDIO_EN
|
||||
uint8_t msi_isnew = 0;
|
||||
|
||||
struct msi *msi = msi_new("R_WAVE_ENCODE", MAX_WAVE_ENCODE_RXBUF, &msi_isnew);
|
||||
if(!msi) {
|
||||
WAVE_INFO("create wave encode msi fail!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
else if(!msi_isnew) {
|
||||
WAVE_INFO("wave encode msi has been create!\r\n");
|
||||
goto wave_encode_init_err;
|
||||
}
|
||||
struct wave_encode_struct *wave_encode_s = (struct wave_encode_struct*)WAVE_CODE_ZALLOC(sizeof(struct wave_encode_struct));
|
||||
if(!wave_encode_s) {
|
||||
WAVE_INFO("wave_encode_s malloc fail!\r\n");
|
||||
goto wave_encode_init_err;
|
||||
}
|
||||
msi->priv = wave_encode_s;
|
||||
msi->action = (msi_action)wave_encode_msi_action;
|
||||
if(os_event_init(&wave_encode_s->event) != RET_OK) {
|
||||
WAVE_INFO("create wave encode event fail!\r\n");
|
||||
goto wave_encode_init_err;
|
||||
}
|
||||
if(filename) {
|
||||
wave_encode_s->wave_fp = osal_fopen((const char*)filename, "wb+");
|
||||
if(wave_encode_s->wave_fp == NULL) {
|
||||
WAVE_INFO("open wave record file %s fail!\r\n", filename);
|
||||
goto wave_encode_init_err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
WAVE_INFO("wave record filename is null!\r\n");
|
||||
goto wave_encode_init_err;
|
||||
}
|
||||
os_memcpy(&(wave_encode_s->wave_head), wav_header, sizeof(TYPE_WAVE_HEAD));
|
||||
osal_fseek(wave_encode_s->wave_fp, sizeof(TYPE_WAVE_HEAD));
|
||||
if(auenc_init->src_msi && (msi_add_output(auenc_init->src_msi, NULL, msi->name) != RET_OK)) {
|
||||
goto wave_encode_init_err;
|
||||
}
|
||||
wave_encode_s->msi = msi;
|
||||
wave_encode_s->src_msi = auenc_init->src_msi;
|
||||
wave_encode_s->samplerate = samplerate;
|
||||
wave_encode_s->destroy_self = auenc_init->destroy_self;
|
||||
wave_encode_s->next_status = AUCODEC_RUN;
|
||||
wave_encode_s->current_status = AUCODEC_RUN;
|
||||
wave_encode_s->task_hdl = os_task_create("wave_encode_thread", wave_encode_thread, (void*)wave_encode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||||
if(wave_encode_s->task_hdl == NULL) {
|
||||
WAVE_INFO("create wave encode task fail!\r\n");
|
||||
goto wave_encode_init_err;
|
||||
}
|
||||
return msi;
|
||||
|
||||
wave_encode_init_err:
|
||||
msi_destroy(msi);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
388
sdk/app/audio_msi/audio_adc.c
Normal file
388
sdk/app/audio_msi/audio_adc.c
Normal file
@@ -0,0 +1,388 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "audio_adc.h"
|
||||
#include "lib/audio/audio_proc/audio_proc.h"
|
||||
|
||||
#define LIMIT(x,y,z) ({\
|
||||
int16_t tmp16;\
|
||||
if(x>y) tmp16=y;\
|
||||
else if(x<z) tmp16=z;\
|
||||
else tmp16=x;\
|
||||
tmp16;\
|
||||
})
|
||||
|
||||
#if AUADC_OUTPUT_SIN
|
||||
static const int16_t sin1khz_table[8] = {
|
||||
5792,8191,5792,0,-5792,-8191,-5792,0,
|
||||
};
|
||||
#endif
|
||||
|
||||
AUPROC_HDL *global_auproc_hdl = NULL;
|
||||
|
||||
struct auadc_struct
|
||||
{
|
||||
uint8_t auadc_stop;
|
||||
uint8_t channels;
|
||||
uint16_t soft_gain;
|
||||
uint32_t data_len;
|
||||
uint32_t sampleRate;
|
||||
uint32_t energy;
|
||||
struct msi *msi;
|
||||
struct os_msgqueue msg;
|
||||
struct os_task *task_hdl;
|
||||
struct fbpool tx_pool;
|
||||
type_ausys_ad_user_cb callback_func;
|
||||
enum ausys_ad_platform platform;
|
||||
#if AUDIO_PROCESS
|
||||
AUPROC_HDL *auproc_hdl;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern uint32_t auadc_calc_energy_asm(volatile int16_t *data, uint16_t soft_gain, uint32_t nsamples);
|
||||
|
||||
void auadc_deal_task(void *d)
|
||||
{
|
||||
volatile int16_t *data = NULL;
|
||||
int32_t ret = 0;
|
||||
uint32_t samples_len;
|
||||
struct framebuff *frame_buf = NULL;
|
||||
struct auadc_struct *auadc_s = (struct auadc_struct*)d;
|
||||
struct ausys_ad_msg ausys_msg;
|
||||
|
||||
auadc_s->auadc_stop = 0;
|
||||
while(1) {
|
||||
if(auadc_s->auadc_stop)
|
||||
break;
|
||||
ret = ausys_ad_get_msg(auadc_s->platform, &ausys_msg, osWaitForever);
|
||||
if((ret == RET_OK) && (ausys_msg.type == AUSYS_AD_MSG_PLAY_DONE)) {
|
||||
get_frame_buf:
|
||||
frame_buf = fbpool_get(&auadc_s->tx_pool, 0, auadc_s->msi);
|
||||
if(frame_buf) {
|
||||
data = (volatile int16_t *)frame_buf->data;
|
||||
os_memcpy((void*)data, (const void*)(ausys_msg.ad_content.fifo_cur_addr), ausys_msg.ad_content.fifo_cur_len);
|
||||
frame_buf->len = ausys_msg.ad_content.fifo_cur_len;
|
||||
frame_buf->time = os_jiffies();
|
||||
samples_len = frame_buf->len/2;
|
||||
#if AUADC_OUTPUT_SIN
|
||||
for(uint32_t i=0; i<samples_len; i++) {
|
||||
*(data+i) = sin1khz_table[i%8];
|
||||
}
|
||||
#else
|
||||
#if AUDIO_PROCESS
|
||||
if(auadc_s->auproc_hdl) {
|
||||
audio_process_data(auadc_s->auproc_hdl, (int16_t*)data, samples_len);
|
||||
}
|
||||
#endif
|
||||
auadc_s->energy = auadc_calc_energy_asm(data, auadc_s->soft_gain, samples_len);
|
||||
#endif
|
||||
frame_buf->mtype = F_AUDIO;
|
||||
frame_buf->stype = FSTYPE_AUDIO_ADC;
|
||||
AUADC_DEBUG("auadc send framebuff:%p\r\n",frame_buf);
|
||||
msi_output_fb(auadc_s->msi, frame_buf);
|
||||
}
|
||||
else {
|
||||
os_sleep_ms(1);
|
||||
goto get_frame_buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
auadc_s->auadc_stop = 2;
|
||||
}
|
||||
|
||||
int32_t auadc_start(struct auadc_struct *s, uint32_t auproc_enable)
|
||||
{
|
||||
struct auadc_struct *auadc_s = (struct auadc_struct*)s;
|
||||
struct framebuff *frame_buf;
|
||||
uint8_t *data;
|
||||
uint32_t data_size;
|
||||
int32_t ret = 0;
|
||||
|
||||
fbpool_init(&auadc_s->tx_pool, MAX_AUADC_TXBUF);
|
||||
data_size = auadc_s->data_len;
|
||||
for(uint32_t i=0; i<MAX_AUADC_TXBUF; i++) {
|
||||
data = (uint8_t*)AUADC_MALLOC(data_size * sizeof(uint8_t));
|
||||
if(!data) {
|
||||
AUADC_INFO("auadc malloc framebuff data fail!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
frame_buf = (auadc_s->tx_pool.pool)+i;
|
||||
frame_buf->data = data;
|
||||
}
|
||||
ausys_ad_record(auadc_s->platform);
|
||||
ret = os_msgq_init(&auadc_s->msg, MAX_AUADC_TXBUF);
|
||||
if(ret != RET_OK) {
|
||||
AUADC_INFO("auadc create msg fail!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
#if AUDIO_PROCESS
|
||||
if(auproc_enable && global_auproc_hdl == NULL) {
|
||||
auadc_s->auproc_hdl = audio_process_init(auadc_s->sampleRate, 1, (auadc_s->sampleRate/1000*AUPROC_FRAME_MS));
|
||||
if(auadc_s->auproc_hdl == NULL) {
|
||||
AUADC_INFO("audio_process_init fail!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
global_auproc_hdl = auadc_s->auproc_hdl;
|
||||
}
|
||||
#endif
|
||||
ausys_ad_register_msg(auadc_s->platform,AUSYS_AD_MSG_PLAY_DONE);
|
||||
auadc_s->task_hdl = os_task_create("auadc_deal_task", auadc_deal_task, auadc_s, AUADC_TASK_PRIORITY, 0, NULL, 1024);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32_t auadc_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct auadc_struct *auadc_s = (struct auadc_struct*)msi->priv;
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(auadc_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
fbpool_put(&auadc_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(auadc_s) {
|
||||
for(uint32_t i=0; i<MAX_AUADC_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (auadc_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
AUADC_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&auadc_s->tx_pool);
|
||||
if(auadc_s->msg.hdl)
|
||||
os_msgq_del(&auadc_s->msg);
|
||||
#if AUDIO_PROCESS
|
||||
if(auadc_s->auproc_hdl) {
|
||||
audio_process_deinit(auadc_s->auproc_hdl);
|
||||
global_auproc_hdl = NULL;
|
||||
}
|
||||
#endif
|
||||
AUADC_FREE(auadc_s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *get_auadc_msi(enum ausys_ad_platform platform)
|
||||
{
|
||||
struct msi *msi = NULL;
|
||||
|
||||
switch(platform) {
|
||||
case AUSYS_AUAD:msi = msi_find("S_AUADC", 1);break;
|
||||
case AUSYS_PDM:msi = msi_find("S_AUPDM", 1);break;
|
||||
case AUSYS_IIS_SLAVER0:msi = msi_find("S_AUIIS0", 1);break;
|
||||
case AUSYS_IIS_SLAVER1:msi = msi_find("S_AUIIS1", 1);break;
|
||||
default:break;
|
||||
}
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
|
||||
int32_t auadc_msi_add_output(enum ausys_ad_platform platform, const char *msi_name)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
struct msi *msi = NULL;
|
||||
|
||||
switch(platform) {
|
||||
case AUSYS_AUAD:msi = msi_find("S_AUADC", 1);break;
|
||||
case AUSYS_PDM:msi = msi_find("S_AUPDM", 1);break;
|
||||
case AUSYS_IIS_SLAVER0:msi = msi_find("S_AUIIS0", 1);break;
|
||||
case AUSYS_IIS_SLAVER1:msi = msi_find("S_AUIIS1", 1);break;
|
||||
default:break;
|
||||
}
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
}
|
||||
else {
|
||||
AUADC_INFO("auadc msi add output fail,auadc msi is null\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
ret = msi_add_output(msi, NULL, msi_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t auadc_msi_del_output(enum ausys_ad_platform platform, const char *msi_name)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
struct msi *msi = NULL;
|
||||
|
||||
switch(platform) {
|
||||
case AUSYS_AUAD:msi = msi_find("S_AUADC", 1);break;
|
||||
case AUSYS_PDM:msi = msi_find("S_AUPDM", 1);break;
|
||||
case AUSYS_IIS_SLAVER0:msi = msi_find("S_AUIIS0", 1);break;
|
||||
case AUSYS_IIS_SLAVER1:msi = msi_find("S_AUIIS1", 1);break;
|
||||
default:break;
|
||||
}
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
}
|
||||
else {
|
||||
AUADC_INFO("auadc msi add output fail,auadc msi is null\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
ret = msi_del_output(msi, NULL, msi_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_adc_get_samplerate(enum ausys_ad_platform platform)
|
||||
{
|
||||
uint32_t samplerate = 8000;
|
||||
struct msi *msi = NULL;
|
||||
struct auadc_struct *auadc_s = NULL;
|
||||
|
||||
switch(platform) {
|
||||
case AUSYS_AUAD:msi = msi_find("S_AUADC", 1);break;
|
||||
case AUSYS_PDM:msi = msi_find("S_AUPDM", 1);break;
|
||||
case AUSYS_IIS_SLAVER0:msi = msi_find("S_AUIIS0", 1);break;
|
||||
case AUSYS_IIS_SLAVER1:msi = msi_find("S_AUIIS1", 1);break;
|
||||
default:break;
|
||||
}
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
auadc_s = (struct auadc_struct*)msi->priv;
|
||||
}
|
||||
if(auadc_s) {
|
||||
samplerate = auadc_s->sampleRate;
|
||||
}
|
||||
return samplerate;
|
||||
}
|
||||
|
||||
int32_t audio_adc_set_soft_gain(enum ausys_ad_platform platform, uint32_t soft_gain)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
struct msi *msi = NULL;
|
||||
struct auadc_struct *auadc_s = NULL;
|
||||
|
||||
switch(platform) {
|
||||
case AUSYS_AUAD:msi = msi_find("S_AUADC", 1);break;
|
||||
case AUSYS_PDM:msi = msi_find("S_AUPDM", 1);break;
|
||||
case AUSYS_IIS_SLAVER0:msi = msi_find("S_AUIIS0", 1);break;
|
||||
case AUSYS_IIS_SLAVER1:msi = msi_find("S_AUIIS1", 1);break;
|
||||
default:break;
|
||||
}
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
auadc_s = (struct auadc_struct*)msi->priv;
|
||||
}
|
||||
if(auadc_s) {
|
||||
auadc_s->soft_gain = soft_gain;
|
||||
ret = RET_OK;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t audio_adc_get_energy(enum ausys_ad_platform platform)
|
||||
{
|
||||
struct msi *msi = NULL;
|
||||
struct auadc_struct *auadc_s = NULL;
|
||||
|
||||
switch(platform) {
|
||||
case AUSYS_AUAD:msi = msi_find("S_AUADC", 1);break;
|
||||
case AUSYS_PDM:msi = msi_find("S_AUPDM", 1);break;
|
||||
case AUSYS_IIS_SLAVER0:msi = msi_find("S_AUIIS0", 1);break;
|
||||
case AUSYS_IIS_SLAVER1:msi = msi_find("S_AUIIS1", 1);break;
|
||||
default:break;
|
||||
}
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
auadc_s = (struct auadc_struct*)msi->priv;
|
||||
}
|
||||
if(auadc_s) {
|
||||
return auadc_s->energy;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t audio_adc_init(enum ausys_ad_platform platform, uint32_t sampleRate, uint32_t channels, uint32_t soft_gain, uint32_t auproc_enable)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
struct msi *msi = NULL;
|
||||
|
||||
switch(platform) {
|
||||
case AUSYS_AUAD:msi = msi_new("S_AUADC", 0, NULL);break;
|
||||
case AUSYS_PDM:msi = msi_new("S_AUPDM", 0, NULL);break;
|
||||
case AUSYS_IIS_SLAVER0:msi = msi_new("S_AUIIS0", 0, NULL);break;
|
||||
case AUSYS_IIS_SLAVER1:msi = msi_new("S_AUIIS1", 0, NULL);break;
|
||||
default:break;
|
||||
}
|
||||
if(msi) {
|
||||
struct auadc_struct *auadc_s = (struct auadc_struct*)AUADC_ZALLOC(sizeof(struct auadc_struct));
|
||||
if(!auadc_s) {
|
||||
AUADC_INFO("malloc auadc_struct fail!\r\n");
|
||||
msi_destroy(msi);
|
||||
return RET_ERR;
|
||||
}
|
||||
msi->enable = 1;
|
||||
msi->action = (msi_action)auadc_msi_action;
|
||||
msi->priv = auadc_s;
|
||||
auadc_s->msi = msi;
|
||||
auadc_s->channels = channels;
|
||||
auadc_s->soft_gain = soft_gain;
|
||||
auadc_s->sampleRate = sampleRate;
|
||||
auadc_s->data_len = sampleRate/1000*channels*2*AUADC_TIME_INTERVAL;
|
||||
auadc_s->platform = platform;
|
||||
ausys_ad_init(
|
||||
auadc_s->platform,
|
||||
auadc_s->sampleRate,
|
||||
16,
|
||||
auadc_s->channels,
|
||||
auadc_s->data_len*AUADC_QUEUE_NUM,
|
||||
auadc_s->data_len,
|
||||
NULL,
|
||||
(uint32_t)auadc_s
|
||||
);
|
||||
ret = auadc_start(auadc_s, auproc_enable);
|
||||
if(ret != RET_OK) {
|
||||
msi_destroy(msi);
|
||||
ausys_ad_deinit(auadc_s->platform);
|
||||
return RET_ERR;
|
||||
}
|
||||
AUADC_INFO("auadc init success!\r\n");
|
||||
return RET_OK;
|
||||
}
|
||||
else {
|
||||
AUADC_INFO("create auadc msi fail!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t audio_adc_deinit(enum ausys_ad_platform platform)
|
||||
{
|
||||
struct msi *msi = NULL;
|
||||
struct auadc_struct *auadc_s = NULL;
|
||||
|
||||
switch(platform) {
|
||||
case AUSYS_AUAD:msi = msi_find("S_AUADC", 1);break;
|
||||
case AUSYS_PDM:msi = msi_find("S_AUPDM", 1);break;
|
||||
case AUSYS_IIS_SLAVER0:msi = msi_find("S_AUIIS0", 1);break;
|
||||
case AUSYS_IIS_SLAVER1:msi = msi_find("S_AUIIS1", 1);break;
|
||||
default:break;
|
||||
}
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
auadc_s = (struct auadc_struct*)msi->priv;
|
||||
}
|
||||
if(!auadc_s) {
|
||||
AUADC_INFO("auadc deinit fail,auadc_s is null!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
auadc_s->auadc_stop = 1;
|
||||
while(auadc_s->auadc_stop != 2)
|
||||
os_sleep_ms(1);
|
||||
ausys_ad_deinit(auadc_s->platform);
|
||||
msi_destroy(msi);
|
||||
return RET_OK;
|
||||
}
|
||||
40
sdk/app/audio_msi/audio_adc.h
Normal file
40
sdk/app/audio_msi/audio_adc.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef _AUDIO_ADC_H_
|
||||
#define _AUDIO_ADC_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "dev/audio/ausys.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define AUADC_MALLOC av_psram_malloc
|
||||
#define AUADC_ZALLOC av_psram_zalloc
|
||||
#define AUADC_FREE av_psram_free
|
||||
#else
|
||||
#define AUADC_MALLOC av_malloc
|
||||
#define AUADC_ZALLOC av_zalloc
|
||||
#define AUADC_FREE av_free
|
||||
#endif
|
||||
|
||||
#define AUADC_DEBUG(fmt, args...) //os_printf(fmt, ##args)
|
||||
#define AUADC_INFO os_printf
|
||||
|
||||
#define AUADC_QUEUE_NUM 3
|
||||
|
||||
#define AUADC_TIME_INTERVAL 20
|
||||
#define AUPROC_FRAME_MS 10
|
||||
#define MAX_AUADC_TXBUF 4
|
||||
#define AUADC_TASK_PRIORITY (OS_TASK_PRIORITY_ABOVE_NORMAL-1)
|
||||
|
||||
#define AUADC_OUTPUT_SIN 0
|
||||
#define AUDIO_PROCESS 1
|
||||
|
||||
int32_t audio_adc_init(enum ausys_ad_platform platform, uint32_t sampleRate, uint32_t channels, uint32_t soft_gain, uint32_t auproc_enable);
|
||||
int32_t audio_adc_deinit(enum ausys_ad_platform platform);
|
||||
int32_t audio_adc_get_samplerate(enum ausys_ad_platform platform);
|
||||
struct msi *get_auadc_msi(enum ausys_ad_platform platform);
|
||||
int32_t auadc_msi_add_output(enum ausys_ad_platform platform, const char *msi_name);
|
||||
int32_t auadc_msi_del_output(enum ausys_ad_platform platform, const char *msi_name);
|
||||
int32_t audio_adc_set_soft_gain(enum ausys_ad_platform platform, uint32_t soft_gain);
|
||||
uint32_t audio_adc_get_energy(enum ausys_ad_platform platform);
|
||||
#endif
|
||||
21
sdk/app/audio_msi/audio_bloop_calc.S
Normal file
21
sdk/app/audio_msi/audio_bloop_calc.S
Normal file
@@ -0,0 +1,21 @@
|
||||
.global auadc_calc_energy_asm
|
||||
|
||||
.align 2
|
||||
|
||||
.type auadc_calc_energy_asm, %function
|
||||
auadc_calc_energy_asm:
|
||||
push r4-r9, r15
|
||||
mov r4, r0
|
||||
mov r5, r1
|
||||
mov r6, r2
|
||||
movi r7, 0
|
||||
calc:
|
||||
ld.hs r8, (r4,0)
|
||||
mulll.s16 r8, r5,r8
|
||||
clipi.s32 r8, r8,16
|
||||
st.h r8, (r4,0)
|
||||
mulall.s16.s r7, r8,r8
|
||||
addi r4, 2
|
||||
bloop r6, calc
|
||||
mov r0, r7
|
||||
pop r4-r9, r15
|
||||
629
sdk/app/audio_msi/audio_dac.c
Normal file
629
sdk/app/audio_msi/audio_dac.c
Normal file
@@ -0,0 +1,629 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "audio_dac.h"
|
||||
#include "dev/audio/ausys.h"
|
||||
#include "dev/audio/ausys_da.h"
|
||||
#include "lib/audio/wsola/wsola_process.h"
|
||||
#include "lib/audio/audio_proc/audio_proc.h"
|
||||
#include "audio_media_ctrl/audio_code_ctrl.h"
|
||||
|
||||
extern AUPROC_HDL *global_auproc_hdl;
|
||||
|
||||
typedef int32_t (*audac_write_func)(int16_t *audac_buf, uint32_t len);
|
||||
|
||||
enum {
|
||||
end_msg = 1,
|
||||
clear_msg,
|
||||
};
|
||||
struct filter_track_struct {
|
||||
AUDIO_TRACK *audio_track[15];
|
||||
uint32_t audio_track_num;
|
||||
struct os_mutex mutex;
|
||||
};
|
||||
struct audac_cache_struct {
|
||||
int16_t *buf;
|
||||
uint32_t s_offset;
|
||||
uint32_t d_offset;
|
||||
uint32_t res_nsamples;
|
||||
struct os_msgqueue cache_msg;
|
||||
};
|
||||
struct audac_struct
|
||||
{
|
||||
uint8_t is_empty;
|
||||
uint8_t hold_empty;
|
||||
uint8_t delete_mode;
|
||||
uint8_t audac_stop;
|
||||
int16_t *empty_buf;
|
||||
int16_t *resample_buf;
|
||||
uint32_t data_nbytes;
|
||||
uint32_t data_nsamples;
|
||||
uint32_t filter_type;
|
||||
uint32_t sampleRate;
|
||||
uint32_t audac_volume;
|
||||
uint32_t call_volume;
|
||||
uint32_t media_volume;
|
||||
uint32_t bell_volume;
|
||||
uint32_t target_volume;
|
||||
float cur_soft_volume;
|
||||
struct msi *msi;
|
||||
struct audac_cache_struct cache_struct;
|
||||
struct filter_track_struct filter_track_s;
|
||||
audac_write_func write_func;
|
||||
struct os_task deal_task_hdl;
|
||||
struct os_task msg_task_hdl;
|
||||
};
|
||||
static struct audac_struct *audac_s = NULL;
|
||||
|
||||
void audac_cache_s_clear(struct audac_cache_struct *audac_cache_s)
|
||||
{
|
||||
audac_cache_s->res_nsamples = audac_s->data_nsamples;
|
||||
audac_cache_s->d_offset = 0;
|
||||
audac_cache_s->s_offset = 0;
|
||||
}
|
||||
|
||||
void set_audac_filter_track(struct audac_struct *audac_s, uint8_t fiter_none, AUDIO_TRACK *audio_track)
|
||||
{
|
||||
struct filter_track_struct *filter_track_s = &(audac_s->filter_track_s);
|
||||
uint32_t wait_empty_cnt = 0;
|
||||
os_mutex_lock(&filter_track_s->mutex, osWaitForever);
|
||||
if(fiter_none == 1) {
|
||||
audac_s->filter_type = FSTYPE_NONE;
|
||||
os_mutex_unlock(&filter_track_s->mutex);
|
||||
return;
|
||||
}
|
||||
if((fiter_none==0) && (audio_track==NULL)) {
|
||||
goto set_audac_filter_type_end;
|
||||
}
|
||||
if((audio_track->priority&0xC0) == play_disabled) {
|
||||
uint8_t del_priority = audio_track->priority;
|
||||
for(uint32_t i=0; i<filter_track_s->audio_track_num; i++) {
|
||||
AUDIO_TRACK *cur_audio_track = filter_track_s->audio_track[i];
|
||||
if(cur_audio_track == audio_track) {
|
||||
os_memmove(&(filter_track_s->audio_track[i]), &(filter_track_s->audio_track[i+1]), (filter_track_s->audio_track_num-(i+1))*sizeof(AUDIO_TRACK*));
|
||||
cur_audio_track = filter_track_s->audio_track[i];
|
||||
}
|
||||
if(((cur_audio_track->priority&0x30)==del_priority) && (cur_audio_track->priority>del_priority)) {
|
||||
cur_audio_track->priority--;
|
||||
}
|
||||
}
|
||||
if(filter_track_s->audio_track[filter_track_s->audio_track_num-1] == audio_track) {
|
||||
audac_s->filter_type = FSTYPE_NONE;
|
||||
while((!audac_s->is_empty) && (wait_empty_cnt++<1000))
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
filter_track_s->audio_track_num--;
|
||||
}
|
||||
else if((audio_track->priority&0xC0) == play_interruptible) {
|
||||
if(filter_track_s->audio_track_num) {
|
||||
for(uint32_t i=(filter_track_s->audio_track_num-1); i>=0; i--) {
|
||||
AUDIO_TRACK *cur_audio_track = filter_track_s->audio_track[i];
|
||||
if((cur_audio_track->priority&0x30) == 0x10) {
|
||||
os_memmove(&(filter_track_s->audio_track[i+2]), &(filter_track_s->audio_track[i+1]), (filter_track_s->audio_track_num-(i+1))*sizeof(AUDIO_TRACK*));
|
||||
filter_track_s->audio_track[i+1] = audio_track;
|
||||
AUDIO_TRACK *new_audio_track = filter_track_s->audio_track[i+1];
|
||||
new_audio_track->priority = cur_audio_track->priority+1;
|
||||
filter_track_s->audio_track_num++;
|
||||
goto set_audac_filter_type_end;
|
||||
}
|
||||
else if(i == 0) {
|
||||
os_memmove(&(filter_track_s->audio_track[1]), &(filter_track_s->audio_track[0]), (filter_track_s->audio_track_num)*sizeof(AUDIO_TRACK*));
|
||||
filter_track_s->audio_track[0] = audio_track;
|
||||
AUDIO_TRACK *new_audio_track = filter_track_s->audio_track[0];
|
||||
new_audio_track->priority = 0x11;
|
||||
filter_track_s->audio_track_num++;
|
||||
goto set_audac_filter_type_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
filter_track_s->audio_track[0] = audio_track;
|
||||
AUDIO_TRACK *new_audio_track = filter_track_s->audio_track[0];
|
||||
new_audio_track->priority = 0x11;
|
||||
filter_track_s->audio_track_num++;
|
||||
}
|
||||
else if((audio_track->priority&0xC0) == play_nonInterruptible) {
|
||||
for(uint32_t i=0; i<filter_track_s->audio_track_num; i++) {
|
||||
AUDIO_TRACK *cur_audio_track = filter_track_s->audio_track[i];
|
||||
if((cur_audio_track->priority&0x30) == 0x20) {
|
||||
os_memmove(&(filter_track_s->audio_track[i+1]), &(filter_track_s->audio_track[i]), (filter_track_s->audio_track_num-i)*sizeof(AUDIO_TRACK*));
|
||||
filter_track_s->audio_track[i] = audio_track;
|
||||
AUDIO_TRACK *new_audio_track = filter_track_s->audio_track[i];
|
||||
new_audio_track->priority = 0x21;
|
||||
filter_track_s->audio_track_num++;
|
||||
for(uint32_t j=(i+1); j<filter_track_s->audio_track_num; j++) {
|
||||
cur_audio_track = filter_track_s->audio_track[i];
|
||||
cur_audio_track->priority++;
|
||||
}
|
||||
goto set_audac_filter_type_end;
|
||||
}
|
||||
else if(i == (filter_track_s->audio_track_num-1)) {
|
||||
filter_track_s->audio_track[i+1] = audio_track;
|
||||
AUDIO_TRACK *new_audio_track = filter_track_s->audio_track[i];
|
||||
new_audio_track->priority = 0x21;
|
||||
filter_track_s->audio_track_num++;
|
||||
goto set_audac_filter_type_end;
|
||||
}
|
||||
}
|
||||
filter_track_s->audio_track[0] = audio_track;
|
||||
AUDIO_TRACK *new_audio_track = filter_track_s->audio_track[0];
|
||||
new_audio_track->priority = 0x21;
|
||||
filter_track_s->audio_track_num++;
|
||||
}
|
||||
set_audac_filter_type_end:
|
||||
|
||||
if(filter_track_s->audio_track_num) {
|
||||
audac_s->filter_type = FSTYPE_AUDIO_PCM;
|
||||
}
|
||||
os_mutex_unlock(&filter_track_s->mutex);
|
||||
}
|
||||
|
||||
AUDIO_TRACK *get_audac_filter_track(struct audac_struct *audac_s)
|
||||
{
|
||||
struct filter_track_struct *filter_track_s = &(audac_s->filter_track_s);
|
||||
if(filter_track_s->audio_track_num && (audac_s->filter_type!=FSTYPE_NONE)) {
|
||||
return filter_track_s->audio_track[filter_track_s->audio_track_num-1];
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void set_audac_samplingrate(struct audac_struct *audac_s, uint32_t sampling_rate)
|
||||
{
|
||||
uint32_t wait_empty_cnt = 0;
|
||||
int32_t ret = 0;
|
||||
|
||||
AUDAC_INFO("change audio dac samplingRate,last:%d,current:%d\r\n",audac_s->sampleRate,sampling_rate);
|
||||
if((sampling_rate == audac_s->sampleRate) || (sampling_rate < 0))
|
||||
return;
|
||||
set_audac_filter_track(audac_s, 1, NULL);
|
||||
while((!audac_s->is_empty) && (wait_empty_cnt++<5000))
|
||||
os_sleep_ms(1);
|
||||
if(global_auproc_hdl && global_auproc_hdl->aec) {
|
||||
ret = audio_resample_config(global_auproc_hdl, sampling_rate, AUDAC_SAMPLERATE);
|
||||
if(ret == RET_OK) {
|
||||
audac_s->sampleRate = sampling_rate;
|
||||
}
|
||||
os_printf("audio_resample_config:%d\n",ret);
|
||||
}
|
||||
else {
|
||||
ret = ausys_da_change_sample_rate(sampling_rate);
|
||||
if(ret == RET_OK) {
|
||||
audac_s->sampleRate = sampling_rate;
|
||||
}
|
||||
}
|
||||
audac_s->data_nbytes = sampling_rate*AUDAC_TIME_INTERVAL*2/1000;
|
||||
audac_s->data_nsamples = audac_s->data_nbytes / 2;
|
||||
set_audac_filter_track(audac_s, 0, NULL);
|
||||
}
|
||||
|
||||
uint32_t get_audac_samplingrate(struct audac_struct *audac_s)
|
||||
{
|
||||
return audac_s->sampleRate;
|
||||
}
|
||||
|
||||
void set_audac_volume(struct audac_struct *audac_s, uint32_t volume)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
if(audac_s->audac_volume == volume)
|
||||
return;
|
||||
ret = ausys_da_change_volume(volume);
|
||||
if(ret == RET_OK)
|
||||
audac_s->audac_volume = volume;
|
||||
}
|
||||
|
||||
uint32_t get_audac_volume(struct audac_struct *audac_s)
|
||||
{
|
||||
return audac_s->audac_volume;
|
||||
}
|
||||
|
||||
void audac_soft_volume_adjust(struct audac_struct *audac_s, int16_t *buf, uint32_t nsamples)
|
||||
{
|
||||
for(uint32_t i=0; i<nsamples; i++) {
|
||||
buf[i] = (int16_t)(((float)buf[i]) * audac_s->cur_soft_volume);
|
||||
if(((uint32_t)(audac_s->cur_soft_volume * 100.0f)) > audac_s->target_volume) {
|
||||
audac_s->cur_soft_volume -= 0.01;
|
||||
}
|
||||
else if(((uint32_t)(audac_s->cur_soft_volume * 100.0f)) < audac_s->target_volume) {
|
||||
audac_s->cur_soft_volume += 0.01;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t audac_write_data(struct audac_struct *audac_s, void* buf, uint32_t nbytes)
|
||||
{
|
||||
int32_t ret = ausys_da_put(buf, nbytes);
|
||||
audac_s->hold_empty = 1;
|
||||
audac_s->is_empty = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void audac_deal_task(void *d)
|
||||
{
|
||||
uint8_t end_stream = 0;
|
||||
uint8_t clear_finish = 1;
|
||||
int16_t *data = NULL;
|
||||
int32_t ret = 0;
|
||||
uint32_t data_nsamples = 0;
|
||||
uint32_t resample_nsamples = 0;
|
||||
uint32_t cache_msg = 0;
|
||||
|
||||
struct framebuff *frame_buf = NULL;
|
||||
struct audac_struct *audac_s = (struct audac_struct*)d;
|
||||
struct audac_cache_struct *audac_cache_s = &audac_s->cache_struct;
|
||||
|
||||
audac_s->audac_stop = 0;
|
||||
audac_cache_s_clear(audac_cache_s);
|
||||
ausys_da_play();
|
||||
while(1) {
|
||||
if(audac_s->audac_stop)
|
||||
break;
|
||||
cache_msg = os_msgq_get2(&audac_cache_s->cache_msg, 0, &ret);
|
||||
if(ret)
|
||||
cache_msg = 0;
|
||||
if(cache_msg == end_msg)
|
||||
end_stream = 1;
|
||||
else if(cache_msg == clear_msg) {
|
||||
clear_finish = 0;
|
||||
audac_cache_s_clear(audac_cache_s);
|
||||
}
|
||||
|
||||
if(!(global_auproc_hdl && global_auproc_hdl->aec)) {
|
||||
if(get_audac_volume(audac_s) != audac_s->target_volume) {
|
||||
set_audac_volume(audac_s, audac_s->target_volume);
|
||||
}
|
||||
}
|
||||
|
||||
frame_buf = msi_get_fb(audac_s->msi,0);
|
||||
if(frame_buf) {
|
||||
data = (int16_t*)frame_buf->data;
|
||||
data_nsamples = (frame_buf->len)/2;
|
||||
audac_cache_s->s_offset = 0;
|
||||
while(data_nsamples >= audac_cache_s->res_nsamples) {
|
||||
if(!clear_finish) {
|
||||
data_nsamples = 0;
|
||||
break;
|
||||
}
|
||||
os_memcpy(audac_cache_s->buf + audac_cache_s->d_offset,
|
||||
data + audac_cache_s->s_offset, audac_cache_s->res_nsamples * sizeof(int16_t));
|
||||
data_nsamples -= audac_cache_s->res_nsamples;
|
||||
audac_cache_s->s_offset += audac_cache_s->res_nsamples;
|
||||
if(global_auproc_hdl && global_auproc_hdl->aec) {
|
||||
audio_resample_data(global_auproc_hdl, audac_cache_s->buf, audac_s->data_nsamples, audac_s->resample_buf, &resample_nsamples);
|
||||
audac_soft_volume_adjust(audac_s, audac_s->resample_buf, resample_nsamples);
|
||||
audac_write_data(audac_s, audac_s->resample_buf, (resample_nsamples << 1));
|
||||
}
|
||||
else {
|
||||
audac_write_data(audac_s, audac_cache_s->buf, audac_s->data_nbytes);
|
||||
}
|
||||
audac_cache_s->res_nsamples = audac_s->data_nsamples;
|
||||
audac_cache_s->d_offset = 0;
|
||||
}
|
||||
if(data_nsamples) {
|
||||
os_memcpy(audac_cache_s->buf + audac_cache_s->d_offset,
|
||||
data + audac_cache_s->s_offset, data_nsamples * sizeof(int16_t));
|
||||
audac_cache_s->res_nsamples -= data_nsamples;
|
||||
audac_cache_s->d_offset += data_nsamples;
|
||||
audac_cache_s->s_offset = 0;
|
||||
data_nsamples = 0;
|
||||
}
|
||||
AUDAC_DEBUG("audac delete framebuff:%p,len:%d\r\n",frame_buf, frame_buf->len);
|
||||
msi_delete_fb(audac_s->msi, frame_buf);
|
||||
frame_buf = NULL;
|
||||
}
|
||||
else {
|
||||
clear_finish = 1;
|
||||
if((audac_cache_s->d_offset > 0) && end_stream) {
|
||||
os_memset(audac_cache_s->buf + audac_cache_s->d_offset, 0,
|
||||
(audac_s->data_nsamples - audac_cache_s->d_offset) * sizeof(int16_t));
|
||||
if(global_auproc_hdl && global_auproc_hdl->aec) {
|
||||
audio_resample_data(global_auproc_hdl, audac_cache_s->buf, audac_s->data_nsamples, audac_s->resample_buf, &resample_nsamples);
|
||||
audac_soft_volume_adjust(audac_s, audac_s->resample_buf, resample_nsamples);
|
||||
audac_write_data(audac_s, audac_s->resample_buf, (resample_nsamples << 1));
|
||||
}
|
||||
else {
|
||||
audac_write_data(audac_s, audac_cache_s->buf, audac_s->data_nbytes);
|
||||
}
|
||||
audac_cache_s_clear(audac_cache_s);
|
||||
data_nsamples = 0;
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
end_stream = 0;
|
||||
}
|
||||
}
|
||||
audac_s->audac_stop = 2;
|
||||
}
|
||||
|
||||
void audac_msg_task(void *d)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
struct ausys_da_msg ausys_msg;
|
||||
|
||||
while(1) {
|
||||
if(audac_s->audac_stop == 2)
|
||||
break;
|
||||
ret = ausys_da_get_msg(&ausys_msg, osWaitForever);
|
||||
if((ret == RET_OK) && (ausys_msg.type & AUSYS_DA_MSG_FIFO_EMPTY)) {
|
||||
audac_s->is_empty = 1;
|
||||
}
|
||||
if((ret == RET_OK) && (ausys_msg.type & AUSYS_DA_MSG_PLAY_HALF)) {
|
||||
if(ausys_msg.da_content.fifo_next_len == 0)
|
||||
audio_process_fardata(global_auproc_hdl, audac_s->empty_buf, audac_s->data_nsamples);
|
||||
else
|
||||
audio_process_fardata(global_auproc_hdl, (int16_t*)(ausys_msg.da_content.fifo_next_addr),
|
||||
ausys_msg.da_content.fifo_next_len / 2);
|
||||
}
|
||||
}
|
||||
audac_s->audac_stop = 3;
|
||||
}
|
||||
|
||||
int32_t audac_start(struct audac_struct *s)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
struct audac_struct *audac_s = (struct audac_struct*)s;
|
||||
struct audac_cache_struct *audac_cache_s = &audac_s->cache_struct;
|
||||
struct filter_track_struct *filter_track_s = &audac_s->filter_track_s;
|
||||
|
||||
audac_cache_s->buf = (int16_t *)AUDAC_ZALLOC(AUDAC_LEN);
|
||||
if(!audac_cache_s->buf) {
|
||||
AUDAC_INFO("audac malloc cache_s buf fail!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
ret = os_msgq_init(&audac_cache_s->cache_msg, 1);
|
||||
if(ret != RET_OK) {
|
||||
AUDAC_INFO("audac create cache_s msg fail!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
ret = os_mutex_init(&filter_track_s->mutex);
|
||||
if(ret != RET_OK) {
|
||||
AUDAC_INFO("audac create filter_track_s mutex fail!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
ausys_da_register_msg(AUSYS_DA_MSG_PLAY_HALF | AUSYS_DA_MSG_FIFO_EMPTY);
|
||||
OS_TASK_INIT("audac_deal_task", &audac_s->deal_task_hdl, audac_deal_task, audac_s, AUDAC_TASK_PRIORITY, NULL, 1024);
|
||||
OS_TASK_INIT("audac_msg_task", &audac_s->msg_task_hdl, audac_msg_task, audac_s, AUDAC_TASK_PRIORITY, NULL, 512);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32_t audac_msi_action(struct msi *msi,uint32_t cmd_id,uint32_t param1,uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
struct framebuff *frame_buf = (struct framebuff*)param1;
|
||||
if(audac_s && (frame_buf->mtype == F_AUDIO)) {
|
||||
AUDIO_TRACK *audac_filter_track = get_audac_filter_track(audac_s);
|
||||
AUDIO_TRACK *audio_track = (AUDIO_TRACK*)(frame_buf->priv);
|
||||
if(audac_filter_track == audio_track) {
|
||||
switch(audio_track->track_type) {
|
||||
case CALL_TRACK:audac_s->target_volume = audac_s->call_volume;break;
|
||||
case MEDIA_TRACK:audac_s->target_volume = audac_s->media_volume;break;
|
||||
case BELL_TRACK:audac_s->target_volume = audac_s->bell_volume;break;
|
||||
default:break;
|
||||
}
|
||||
if(audio_track->samplerate != get_audac_samplingrate(audac_s)) {
|
||||
set_audac_samplingrate(audac_s, audio_track->samplerate);
|
||||
}
|
||||
ret = RET_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_TRANS_FB_END:
|
||||
{
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(audac_s->delete_mode) {
|
||||
frame_buf = msi_get_fb(msi, 0);
|
||||
msi_delete_fb(msi, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_AUDAC:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(!audac_s) {
|
||||
AUDAC_INFO("audac do cmd:%d fail!\r\n",param1);
|
||||
break;
|
||||
}
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUDAC_SET_FILTER_TRACK:
|
||||
{
|
||||
AUDIO_TRACK *audio_track = (AUDIO_TRACK*)param2;
|
||||
set_audac_filter_track(audac_s, 0, audio_track);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_GET_FILTER_TRACK:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)get_audac_filter_track(audac_s);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_SET_CALL_VOLUME:
|
||||
{
|
||||
audac_s->call_volume = param2;
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_GET_CALL_VOLUME:
|
||||
{
|
||||
*((uint32_t*)param2) = audac_s->call_volume;
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_SET_MEDIA_VOLUME:
|
||||
{
|
||||
audac_s->media_volume = param2;
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_GET_MEDIA_VOLUME:
|
||||
{
|
||||
*((uint32_t*)param2) = audac_s->media_volume;
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_SET_BELL_VOLUME:
|
||||
{
|
||||
audac_s->bell_volume = param2;
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_GET_BELL_VOLUME:
|
||||
{
|
||||
*((uint32_t*)param2) = audac_s->bell_volume;
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_CLEAR_STREAM:
|
||||
{
|
||||
if(param2 == (uint32_t)get_audac_filter_track(audac_s)) {
|
||||
os_msgq_put(&audac_s->cache_struct.cache_msg, clear_msg, osWaitForever);
|
||||
ret = RET_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_END_STREAM:
|
||||
{
|
||||
if(param2 == (uint32_t)get_audac_filter_track(audac_s)) {
|
||||
os_msgq_put(&audac_s->cache_struct.cache_msg, end_msg, osWaitForever);
|
||||
ret = RET_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_DELETE_MODE:
|
||||
{
|
||||
audac_s->delete_mode = (uint8_t)param2;
|
||||
}
|
||||
case MSI_AUDAC_GET_EMPTY:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(audac_s->is_empty && audac_s->hold_empty);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_HOLD_EMPTY:
|
||||
{
|
||||
audac_s->hold_empty = (uint8_t)param2;
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUDAC_TEST_MODE:
|
||||
{
|
||||
if(param2 == 1) {
|
||||
set_audac_filter_track(audac_s, 1, NULL);
|
||||
set_audac_samplingrate(audac_s, 48000);
|
||||
ausys_da_test_mode(AUSYS_DA_TEST_OPEN, 0, 0, 0);
|
||||
ausys_da_test_mode(AUSYS_DA_TEST_PLAY_SINE, 0, 0, 0);
|
||||
}
|
||||
else if(param2 == 0) {
|
||||
ausys_da_test_mode(AUSYS_DA_TEST_CLOSE, 0, 0, 0);
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AUDAC_INFO("audac invalid commond!\r\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(audac_s) {
|
||||
if(audac_s->cache_struct.buf)
|
||||
AUDAC_FREE(audac_s->cache_struct.buf);
|
||||
if(audac_s->cache_struct.cache_msg.hdl)
|
||||
os_msgq_del(&audac_s->cache_struct.cache_msg);
|
||||
if(audac_s->filter_track_s.mutex.hdl)
|
||||
os_mutex_del(&audac_s->filter_track_s.mutex);
|
||||
if(audac_s->empty_buf) {
|
||||
AUDAC_FREE(audac_s->empty_buf);
|
||||
}
|
||||
if(audac_s->resample_buf) {
|
||||
AUDAC_FREE(audac_s->resample_buf);
|
||||
}
|
||||
AUDAC_FREE(audac_s);
|
||||
audac_s = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t audio_dac_init(void)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
struct msi *msi = msi_new("R_AUDAC", MAX_AUDAC_RXBUF,NULL);
|
||||
if(msi)
|
||||
{
|
||||
audac_s = (struct audac_struct *)AUDAC_ZALLOC(sizeof(struct audac_struct));
|
||||
if(!audac_s) {
|
||||
AUDAC_INFO("malloc audac_struct fail!\r\n");
|
||||
msi_destroy(msi);
|
||||
return RET_ERR;
|
||||
}
|
||||
msi->enable = 1;
|
||||
msi->action = (msi_action)audac_msi_action;
|
||||
audac_s->msi = msi;
|
||||
audac_s->sampleRate = AUDAC_SAMPLERATE;
|
||||
audac_s->data_nbytes = audac_s->sampleRate*AUDAC_TIME_INTERVAL*2/1000;
|
||||
audac_s->data_nsamples = audac_s->data_nbytes / 2;
|
||||
audac_s->empty_buf = (int16_t*)AUDAC_ZALLOC(sizeof(int16_t) * audac_s->data_nsamples);
|
||||
audac_s->resample_buf = (int16_t*)AUDAC_ZALLOC(sizeof(int16_t) * audac_s->data_nsamples);
|
||||
if((audac_s->empty_buf==NULL) || (audac_s->resample_buf==NULL)) {
|
||||
AUDAC_INFO("malloc audac empty_buf fail!\r\n");
|
||||
msi_destroy(audac_s->msi);
|
||||
return RET_ERR;
|
||||
}
|
||||
audac_s->is_empty = 1;
|
||||
audac_s->hold_empty = 1;
|
||||
audac_s->call_volume = 100;
|
||||
audac_s->media_volume = 100;
|
||||
audac_s->bell_volume = 100;
|
||||
audac_s->target_volume = 100;
|
||||
audac_s->audac_volume = 100;
|
||||
ausys_da_init(
|
||||
audac_s->sampleRate,
|
||||
16,
|
||||
1,
|
||||
AUSYS_AUDA,
|
||||
AUDAC_LEN*AUDAC_QUEUE_NUM,
|
||||
AUDAC_LEN,
|
||||
audac_s->data_nbytes
|
||||
);
|
||||
ret = audac_start(audac_s);
|
||||
if(ret != RET_OK) {
|
||||
ausys_da_deinit();
|
||||
msi_destroy(audac_s->msi);
|
||||
return RET_ERR;
|
||||
}
|
||||
AUDAC_INFO("audio dac msi init!\r\n");
|
||||
return RET_OK;
|
||||
}
|
||||
else {
|
||||
AUDAC_INFO("create auadc msi fail!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t audio_dac_deinit(void)
|
||||
{
|
||||
if(!audac_s) {
|
||||
AUDAC_INFO("audac deinit fail,auadc_s is null!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
audac_s->audac_stop = 1;
|
||||
while(audac_s->audac_stop != 3)
|
||||
os_sleep_ms(1);
|
||||
ausys_da_deinit();
|
||||
msi_destroy(audac_s->msi);
|
||||
return RET_OK;
|
||||
}
|
||||
47
sdk/app/audio_msi/audio_dac.h
Normal file
47
sdk/app/audio_msi/audio_dac.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef _AUDIO_DAC_H_
|
||||
#define _AUDIO_DAC_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define AUDAC_MALLOC av_psram_malloc
|
||||
#define AUDAC_ZALLOC av_psram_zalloc
|
||||
#define AUDAC_FREE av_psram_free
|
||||
#else
|
||||
#define AUDAC_MALLOC av_malloc
|
||||
#define AUDAC_ZALLOC av_zalloc
|
||||
#define AUDAC_FREE av_free
|
||||
#endif
|
||||
|
||||
#define AUDAC_DEBUG(fmt, args...) //os_printf(fmt, ##args)
|
||||
#define AUDAC_INFO os_printf
|
||||
/*support cmd*/
|
||||
/*
|
||||
MSI_AUDAC_SET_FILTER_TRACK,
|
||||
MSI_AUDAC_GET_FILTER_TRACK,
|
||||
MSI_AUDAC_SET_CALL_VOLUME,
|
||||
MSI_AUDAC_GET_CALL_VOLUME,
|
||||
MSI_AUDAC_SET_MEDIA_VOLUME,
|
||||
MSI_AUDAC_GET_MEDIA_VOLUME,
|
||||
MSI_AUDAC_SET_BELL_VOLUME,
|
||||
MSI_AUDAC_GET_BELL_VOLUME,
|
||||
MSI_AUDAC_CLEAR_STREAM,
|
||||
MSI_AUDAC_END_STREAM,
|
||||
MSI_AUDAC_GET_EMPTY,
|
||||
MSI_AUDAC_HOLD_EMPTY,
|
||||
MSI_AUDAC_TEST_MODE,
|
||||
*/
|
||||
|
||||
#define AUDAC_SAMPLERATE 8000
|
||||
#define AUDAC_QUEUE_NUM 3
|
||||
|
||||
#define AUDAC_TIME_INTERVAL 20
|
||||
#define AUDAC_LEN 1920 //按48k、20ms为最大长度配置
|
||||
#define MAX_AUDAC_RXBUF 24
|
||||
#define AUDAC_TASK_PRIORITY OS_TASK_PRIORITY_ABOVE_NORMAL
|
||||
|
||||
extern int32_t audio_dac_init(void);
|
||||
extern int32_t audio_dac_deinit(void);
|
||||
#endif
|
||||
206
sdk/app/audio_usb_msi/audio_usbh_mic_msi.c
Normal file
206
sdk/app/audio_usb_msi/audio_usbh_mic_msi.c
Normal file
@@ -0,0 +1,206 @@
|
||||
#include "lib/audio/uac/uac_host.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "audio_usbh_msi.h"
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define AUDIO_LEN (1024)
|
||||
#define MAX_UAC_APP 4
|
||||
|
||||
static int32_t uac_host_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct uac_msi_s *uac_mic = (struct uac_msi_s *)msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
fbpool_destroy(&uac_mic->tx_pool);
|
||||
if(uac_mic) {
|
||||
STREAM_LIBC_FREE(uac_mic);
|
||||
msi->priv = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
// os_printf("fb:%X\n",fb);
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
fbpool_put(&uac_mic->tx_pool, fb);
|
||||
// 不需要内核去释放fb
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void get_usbmic_audio(void *d)
|
||||
{
|
||||
uint32_t usbmic_timeout = 0;
|
||||
uint32_t usb_dma_irq_count = 0;
|
||||
struct framebuff *fb = NULL;
|
||||
int16 *realdata = NULL;
|
||||
int16 *audio_addr = NULL;
|
||||
uint32_t audio_len = 0;
|
||||
uint32_t stop_flag = 0;
|
||||
UAC_MANAGE *usbmic_manage = NULL;
|
||||
struct msi *msi = (struct msi *)d;
|
||||
if(!msi)
|
||||
{
|
||||
os_printf("open usbmic stream err\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct uac_msi_s *uac_mic = (struct uac_msi_s *)msi->priv;
|
||||
|
||||
while(1)
|
||||
{
|
||||
os_event_wait(&uac_mic->evt, UAC_TASK_STOP, (uint32 *)&stop_flag, OS_EVENT_WMODE_OR, 0);
|
||||
if (stop_flag)
|
||||
{
|
||||
goto get_usbmic_audio_end;
|
||||
}
|
||||
|
||||
if (usbmic_timeout > 500) {
|
||||
if(usb_dma_irq_count == *(uac_mic->p_usb_dma_irq_time)) {
|
||||
goto get_usbmic_audio_end;
|
||||
}
|
||||
usb_dma_irq_count = *(uac_mic->p_usb_dma_irq_time);
|
||||
usbmic_timeout = 0;
|
||||
}
|
||||
usbmic_timeout++;
|
||||
|
||||
usbmic_manage = get_usbmic_frame();
|
||||
if (usbmic_manage)
|
||||
{
|
||||
fb = fbpool_get(&uac_mic->tx_pool, 0, uac_mic->msi);
|
||||
if(fb)
|
||||
{
|
||||
_os_printf("L");
|
||||
audio_len = get_uac_frame_datalen(usbmic_manage);
|
||||
audio_addr = (int16 *)get_uac_frame_data(usbmic_manage);
|
||||
realdata = (int16 *)STREAM_LIBC_ZALLOC(AUDIO_LEN);
|
||||
if (realdata && audio_addr) {
|
||||
fb->data = (uint8_t*)realdata;
|
||||
os_memcpy(realdata, audio_addr, audio_len);
|
||||
realdata = NULL;
|
||||
audio_addr = NULL;
|
||||
} else {
|
||||
os_printf("%s %d malloc failed\n", __FUNCTION__, __LINE__);
|
||||
goto get_usbmic_audio_end;
|
||||
}
|
||||
|
||||
fb->mtype = F_AUDIO;
|
||||
fb->stype = FSTYPE_AUDIO_USB_MIC;
|
||||
fb->len = audio_len;
|
||||
|
||||
msi_output_fb(msi, fb);
|
||||
fb = NULL;
|
||||
|
||||
del_usbmic_frame(usbmic_manage);
|
||||
usbmic_manage = NULL;
|
||||
realdata = NULL;
|
||||
audio_addr = NULL;
|
||||
audio_len = 0;
|
||||
|
||||
usbmic_timeout = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
del_usbmic_frame(usbmic_manage);
|
||||
usbmic_manage = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// _os_printf("M");
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
get_usbmic_audio_end:
|
||||
if (usbmic_manage)
|
||||
{
|
||||
del_usbmic_frame(usbmic_manage);
|
||||
usbmic_manage = NULL;
|
||||
}
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
if(realdata)
|
||||
{
|
||||
STREAM_LIBC_FREE(realdata);
|
||||
realdata = NULL;
|
||||
}
|
||||
usbmic_room_del();
|
||||
msi_destroy(msi);
|
||||
return;
|
||||
}
|
||||
|
||||
static void usbmic_audio_stream_init(int* p_usb_dma_irq_time)
|
||||
{
|
||||
struct msi *msi = NULL;
|
||||
usb_host_enum_finish_init_start:
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
msi = msi_new(S_USB_MIC, 0, NULL);
|
||||
|
||||
if(!msi) {
|
||||
_os_printf("%s open stream err!\n",__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
struct uac_msi_s *uac_mic = (struct uac_msi_s *)msi->priv;
|
||||
if(!uac_mic){
|
||||
uac_mic = (struct uac_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct uac_msi_s));
|
||||
msi->priv = (void *)uac_mic;
|
||||
uac_mic->msi = msi;
|
||||
uac_mic->p_usb_dma_irq_time = p_usb_dma_irq_time;
|
||||
msi->action = (msi_action)uac_host_action;
|
||||
os_event_init(&uac_mic->evt);
|
||||
fbpool_init(&uac_mic->tx_pool, MAX_UAC_APP);
|
||||
|
||||
msi->enable = 1;
|
||||
msi_add_output(msi, NULL, R_USB_SPK);
|
||||
|
||||
os_task_create("usbmic_audio", get_usbmic_audio, (void *)msi, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 发送一个evt,通知线程需要退出了
|
||||
os_event_set(&uac_mic->evt, UAC_TASK_STOP, NULL);
|
||||
|
||||
// 等到线程已经退出
|
||||
os_event_wait(&uac_mic->evt, UAC_TASK_EXIT, NULL, OS_EVENT_WMODE_OR, -1);
|
||||
|
||||
msi->name = NULL;
|
||||
msi_destroy(msi);
|
||||
|
||||
goto usb_host_enum_finish_init_start;
|
||||
}
|
||||
}
|
||||
|
||||
void usbmic_audio_stream_deinit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void usbmic_enum_finish(int* p_usb_dma_irq_time)
|
||||
{
|
||||
usbmic_audio_stream_init(p_usb_dma_irq_time);
|
||||
}
|
||||
27
sdk/app/audio_usb_msi/audio_usbh_msi.h
Normal file
27
sdk/app/audio_usb_msi/audio_usbh_msi.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef _AUDIO_USB_MSI_H_
|
||||
#define _AUDIO_USB_MSI_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "stream_frame.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
|
||||
enum uac_app_usb
|
||||
{
|
||||
UAC_TASK_EXIT = BIT(0),
|
||||
UAC_TASK_STOP = BIT(1),
|
||||
};
|
||||
|
||||
struct uac_msi_s
|
||||
{
|
||||
struct os_task task;
|
||||
struct msi *msi;
|
||||
struct os_event evt;
|
||||
struct fbpool tx_pool;
|
||||
int* p_usb_dma_irq_time;
|
||||
};
|
||||
|
||||
|
||||
void usbmic_enum_finish(int* p_usb_dma_irq_time);
|
||||
void usbspk_enum_finish(int* p_usb_dma_irq_time);
|
||||
|
||||
#endif
|
||||
203
sdk/app/audio_usb_msi/audio_usbh_spk_msi.c
Normal file
203
sdk/app/audio_usb_msi/audio_usbh_spk_msi.c
Normal file
@@ -0,0 +1,203 @@
|
||||
#include "lib/audio/uac/uac_host.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "audio_usbh_msi.h"
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define AUDIO_LEN (1024)
|
||||
#define MAX_UAC_APP 8
|
||||
|
||||
static int32_t uac_host_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct uac_msi_s *uac_spk = (struct uac_msi_s *)msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if (uac_spk)
|
||||
{
|
||||
STREAM_LIBC_FREE(uac_spk);
|
||||
msi->priv = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
if(fb->mtype != F_AUDIO)
|
||||
{
|
||||
ret = RET_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
// USB MIC 回环数据
|
||||
if(fb->stype != FSTYPE_AUDIO_USB_MIC)
|
||||
{
|
||||
ret = RET_ERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void send_usbspk_audio(void *d)
|
||||
{
|
||||
int16 *buf = NULL;
|
||||
uint32 len = 0;
|
||||
uint8_t *audio_addr = NULL;
|
||||
UAC_MANAGE *usbspk_manage = NULL;
|
||||
uint32_t usbspk_timeout = 0;
|
||||
uint32_t usb_dma_irq_count = 0;
|
||||
uint32_t stop_flag = 0;
|
||||
struct framebuff *fb = NULL;
|
||||
|
||||
struct msi* msi = (struct msi*)d;
|
||||
if(!msi)
|
||||
{
|
||||
os_printf("open usbspk stream err\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct uac_msi_s *uac_spk = (struct uac_msi_s *)msi->priv;
|
||||
|
||||
while(1)
|
||||
{
|
||||
os_event_wait(&uac_spk->evt, UAC_TASK_STOP, (uint32 *)&stop_flag, OS_EVENT_WMODE_OR, 0);
|
||||
if (stop_flag)
|
||||
{
|
||||
goto send_usbspk_audio_end;
|
||||
}
|
||||
|
||||
if(usbspk_timeout > 500) {
|
||||
if(usb_dma_irq_count == *(uac_spk->p_usb_dma_irq_time)) {
|
||||
goto send_usbspk_audio_end;
|
||||
}
|
||||
usb_dma_irq_count = *(uac_spk->p_usb_dma_irq_time);
|
||||
usbspk_timeout = 0;
|
||||
}
|
||||
usbspk_timeout++;
|
||||
|
||||
fb = msi_get_fb(msi, 0);
|
||||
if(fb) {
|
||||
usbspk_manage = get_usbspk_new_frame(0);
|
||||
if(usbspk_manage)
|
||||
{
|
||||
_os_printf("S");
|
||||
buf = (int16 *)fb->data;
|
||||
len = fb->len;
|
||||
audio_addr = get_uac_frame_data(usbspk_manage);
|
||||
|
||||
if (buf && audio_addr) {
|
||||
os_memcpy((uint8*)audio_addr, buf, len);
|
||||
buf = NULL;
|
||||
audio_addr = NULL;
|
||||
} else {
|
||||
os_printf("%s %d audio data get failed\n", __FUNCTION__, __LINE__);
|
||||
goto send_usbspk_audio_end;
|
||||
}
|
||||
|
||||
set_uac_frame_datalen(usbspk_manage, len);
|
||||
set_uac_frame_sta(usbspk_manage, 1);
|
||||
put_usbspk_frame_to_use(usbspk_manage);
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
|
||||
len = 0;
|
||||
buf = NULL;
|
||||
audio_addr = NULL;
|
||||
usbspk_manage = NULL;
|
||||
|
||||
usbspk_timeout = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// _os_printf("E");
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
send_usbspk_audio_end:
|
||||
if (usbspk_manage)
|
||||
{
|
||||
del_usbspk_frame(usbspk_manage);
|
||||
usbspk_manage = NULL;
|
||||
}
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
usbspk_room_del();
|
||||
msi_destroy(msi);
|
||||
return;
|
||||
}
|
||||
|
||||
static void usbspk_audio_stream_init(int* p_usb_dma_irq_time)
|
||||
{
|
||||
struct msi *msi = NULL;
|
||||
usb_host_enum_finish_init_start:
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
msi = msi_new(R_USB_SPK, MAX_UAC_APP, NULL);
|
||||
|
||||
if (!msi)
|
||||
{
|
||||
_os_printf("%s open stream err!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
struct uac_msi_s *uac_spk = (struct uac_msi_s *)msi->priv;
|
||||
if (!uac_spk)
|
||||
{
|
||||
uac_spk = (struct uac_msi_s *)STREAM_LIBC_ZALLOC(sizeof(struct uac_msi_s));
|
||||
msi->priv = (void *)uac_spk;
|
||||
uac_spk->msi = msi;
|
||||
uac_spk->p_usb_dma_irq_time = p_usb_dma_irq_time;
|
||||
msi->action = (msi_action)uac_host_action;
|
||||
os_event_init(&uac_spk->evt);
|
||||
|
||||
msi->enable = 1;
|
||||
|
||||
os_task_create("usbspk_audio", send_usbspk_audio, (void *)msi, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 发送一个evt,通知线程需要退出了
|
||||
os_event_set(&uac_spk->evt, UAC_TASK_STOP, NULL);
|
||||
|
||||
// 等到线程已经退出
|
||||
os_event_wait(&uac_spk->evt, UAC_TASK_EXIT, NULL, OS_EVENT_WMODE_OR, -1);
|
||||
|
||||
msi->name = NULL;
|
||||
msi_destroy(msi);
|
||||
|
||||
goto usb_host_enum_finish_init_start;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void usbspk_audio_stream_deinit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void usbspk_enum_finish(int* p_usb_dma_irq_time)
|
||||
{
|
||||
usbspk_audio_stream_init(p_usb_dma_irq_time);
|
||||
}
|
||||
293
sdk/app/autpc_msi/autpc_msi.c
Normal file
293
sdk/app/autpc_msi/autpc_msi.c
Normal file
@@ -0,0 +1,293 @@
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/audio/wsola/wsola_process.h"
|
||||
#include "autpc_msi.h"
|
||||
|
||||
#define MAX_AUTPC_RXBUF 1
|
||||
#define MAX_AUTPC_TXBUF 4
|
||||
|
||||
typedef struct {
|
||||
struct msi *msi;
|
||||
struct fbpool tx_pool;
|
||||
char *msi_name;
|
||||
uint32_t have_next_time;
|
||||
uint32_t next_time;
|
||||
uint32_t direct_to_dac;
|
||||
float speed;
|
||||
float pitch;
|
||||
WsolaStream *wsola_stream;
|
||||
AUDIO_TRACK *audio_track;
|
||||
} autpc_struct;
|
||||
|
||||
static int32_t autpc_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
autpc_struct *autpc_s = (autpc_struct*)msi->priv;
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
struct framebuff *recv_frame_buf = (struct framebuff *)param1;
|
||||
struct framebuff *send_frame_buf = NULL;
|
||||
AUDIO_TRACK *audac_fiter_track = NULL;
|
||||
uint32_t interval_time = 0;
|
||||
if(recv_frame_buf->mtype == F_AUDIO) {
|
||||
uint32_t data_nsamples = (recv_frame_buf->len) / 2;
|
||||
uint32_t nsamples = 0;
|
||||
uint32_t offset = 0;
|
||||
float current_pitch = 1.0f;
|
||||
float current_speed = 1.0f;
|
||||
current_speed = wsolaStream_get_speed(autpc_s->wsola_stream);
|
||||
current_pitch = wsolaStream_get_pitch(autpc_s->wsola_stream);
|
||||
if(current_pitch != autpc_s->pitch) {
|
||||
msi_do_cmd(msi, MSI_CMD_AUTPC, MSI_AUTPC_END_STREAM, 0);
|
||||
wsolaStream_set_pitch(autpc_s->wsola_stream, autpc_s->pitch);
|
||||
}
|
||||
if(current_speed != autpc_s->speed) {
|
||||
wsolaStream_set_speed(autpc_s->wsola_stream, autpc_s->speed);
|
||||
}
|
||||
while(data_nsamples > 0) {
|
||||
nsamples = wsolaStream_input_data(autpc_s->wsola_stream, (int16_t*)(recv_frame_buf->data+offset), data_nsamples);
|
||||
data_nsamples -= nsamples;
|
||||
offset += (nsamples * 2);
|
||||
nsamples = wsolaStream_output_available(autpc_s->wsola_stream);
|
||||
if(nsamples > 0) {
|
||||
while(!send_frame_buf) {
|
||||
send_frame_buf = fbpool_get(&autpc_s->tx_pool, 0, autpc_s->msi);
|
||||
if(!send_frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
send_frame_buf->data = (uint8_t*)AUTPC_MALLOC(sizeof(int16_t) * nsamples);
|
||||
if(send_frame_buf->data == NULL) {
|
||||
os_printf("autpc msi malloc send_frame_buf->data fail\n");
|
||||
msi_delete_fb(autpc_s->msi, send_frame_buf);
|
||||
break;
|
||||
}
|
||||
nsamples = wsolaStream_output_data(autpc_s->wsola_stream, (int16_t*)(send_frame_buf->data), nsamples);
|
||||
send_frame_buf->len = nsamples * 2;
|
||||
send_frame_buf->mtype = recv_frame_buf->mtype;
|
||||
send_frame_buf->stype = recv_frame_buf->stype;
|
||||
send_frame_buf->priv = autpc_s->audio_track;
|
||||
if(autpc_s->have_next_time == 0) {
|
||||
send_frame_buf->time = recv_frame_buf->time;
|
||||
autpc_s->have_next_time = 1;
|
||||
autpc_s->next_time = send_frame_buf->time;
|
||||
}
|
||||
else {
|
||||
send_frame_buf->time = autpc_s->next_time;
|
||||
}
|
||||
msi_output_fb(autpc_s->msi, send_frame_buf);
|
||||
msi_output_cmd(autpc_s->msi, MSI_CMD_AUDAC, MSI_AUDAC_GET_FILTER_TRACK, (uint32_t)(&audac_fiter_track));
|
||||
if((autpc_s->direct_to_dac) && (audac_fiter_track != autpc_s->audio_track)) {
|
||||
AUDIO_TRACK *audio_trcak = send_frame_buf->priv;
|
||||
interval_time = (send_frame_buf->len>>1)*1000/(audio_trcak->samplerate);
|
||||
os_sleep_ms(interval_time);
|
||||
}
|
||||
send_frame_buf = NULL;
|
||||
autpc_s->next_time += nsamples * 1000 / wsolaStream_get_sampleRate(autpc_s->wsola_stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(autpc_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->data) {
|
||||
AUTPC_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
fbpool_put(&autpc_s->tx_pool, frame_buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(autpc_s) {
|
||||
for(uint32_t i=0; i<MAX_AUTPC_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (autpc_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
AUTPC_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&autpc_s->tx_pool);
|
||||
if(autpc_s->msi_name) {
|
||||
AUTPC_FREE(autpc_s->msi_name);
|
||||
}
|
||||
if(autpc_s->wsola_stream) {
|
||||
wsolaStream_deinit(autpc_s->wsola_stream);
|
||||
autpc_s->wsola_stream = NULL;
|
||||
}
|
||||
AUTPC_FREE(autpc_s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_AUTPC:
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if(!autpc_s) {
|
||||
break;
|
||||
}
|
||||
uint32_t cmd_self = (uint32_t)param1;
|
||||
switch(cmd_self) {
|
||||
case MSI_AUTPC_SET_SPEED:
|
||||
{
|
||||
autpc_s->speed = ((float)param2)/100.0f;
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUTPC_GET_SPEED:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(autpc_s->speed*100);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUTPC_SET_PITCH:
|
||||
{
|
||||
autpc_s->pitch = ((float)param2)/100.0f;
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUTPC_GET_PITCH:
|
||||
{
|
||||
*((uint32_t*)param2) = (uint32_t)(autpc_s->pitch*100);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
case MSI_AUTPC_END_STREAM:
|
||||
{
|
||||
struct framebuff *send_frame_buf = NULL;
|
||||
uint32_t nsamples = 0;
|
||||
wsolaStream_flush(autpc_s->wsola_stream);
|
||||
nsamples = wsolaStream_output_available(autpc_s->wsola_stream);
|
||||
if(nsamples > 0) {
|
||||
while(!send_frame_buf) {
|
||||
send_frame_buf = fbpool_get(&autpc_s->tx_pool, 0, autpc_s->msi);
|
||||
if(!send_frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
send_frame_buf->data = (uint8_t*)AUTPC_MALLOC(sizeof(int16_t) * nsamples);
|
||||
if(send_frame_buf->data == NULL) {
|
||||
os_printf("autpc msi malloc send_frame_buf->data fail\n");
|
||||
msi_delete_fb(autpc_s->msi, send_frame_buf);
|
||||
break;
|
||||
}
|
||||
nsamples = wsolaStream_output_data(autpc_s->wsola_stream, (int16_t*)(send_frame_buf->data), nsamples);
|
||||
send_frame_buf->len = nsamples * 2;
|
||||
send_frame_buf->time = autpc_s->next_time;
|
||||
send_frame_buf->priv = autpc_s->audio_track;
|
||||
msi_output_fb(autpc_s->msi, send_frame_buf);
|
||||
}
|
||||
autpc_s->have_next_time = 0;
|
||||
wsolaStream_clean(autpc_s->wsola_stream);
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *autpc_msi_init(uint32_t samplerate, uint32_t speed, uint32_t pitch, uint32_t max_inputSamples, AUDIO_TRACK *audio_track)
|
||||
{
|
||||
struct framebuff *frame_buf = NULL;
|
||||
struct msi *msi = NULL;
|
||||
char *msi_name = NULL;
|
||||
|
||||
msi_name = (char*)AUTPC_ZALLOC(sizeof(char)*20);
|
||||
if(msi_name == NULL) {
|
||||
os_printf("alloc autpc msi namefail\n");
|
||||
return NULL;
|
||||
}
|
||||
os_snprintf(msi_name, 20, "SR_AUTPC_""%04d", (int)(os_jiffies()));
|
||||
msi = msi_new((const char*)msi_name, MAX_AUTPC_RXBUF, NULL);
|
||||
if(msi == NULL) {
|
||||
os_printf("create autpc msi fail\n");
|
||||
return NULL;
|
||||
}
|
||||
autpc_struct *autpc_s = (autpc_struct*)AUTPC_ZALLOC(sizeof(autpc_struct));
|
||||
if(autpc_s == NULL) {
|
||||
AUTPC_FREE(msi_name);
|
||||
msi_destroy(msi);
|
||||
os_printf("alloc autpc_s fail!\n");
|
||||
return NULL;
|
||||
}
|
||||
fbpool_init(&autpc_s->tx_pool, MAX_AUTPC_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_AUTPC_TXBUF; i++) {
|
||||
frame_buf = (autpc_s->tx_pool.pool)+i;
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
msi->priv = autpc_s;
|
||||
autpc_s->msi = msi;
|
||||
autpc_s->msi_name = msi_name;
|
||||
autpc_s->msi->enable = 1;
|
||||
autpc_s->msi->action = autpc_msi_action;
|
||||
autpc_s->audio_track = audio_track;
|
||||
autpc_s->wsola_stream = wsolaStream_init(samplerate, 1, (float)speed/100.0f, (float)pitch/100.0f, max_inputSamples*2, max_inputSamples*4);
|
||||
if(autpc_s->wsola_stream == NULL) {
|
||||
msi_destroy(msi);
|
||||
os_printf("wsolaStream init fail!\n");
|
||||
return NULL;
|
||||
}
|
||||
autpc_s->speed = ((float)speed)/100.0f;
|
||||
autpc_s->pitch = ((float)pitch)/100.0f;
|
||||
return msi;
|
||||
}
|
||||
|
||||
int32_t autpc_msi_add_output(struct msi *msi, const char *msi_name)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
if(msi_name == NULL) {
|
||||
os_printf("autpc msi add output fail,msi_name is null\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
if(msi == NULL) {
|
||||
os_printf("autpc msi add output fail,autpc msi is null\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
ret = msi_add_output(msi, NULL, msi_name);
|
||||
if((os_strncmp(msi_name, "R_AUDAC", os_strlen("R_AUDAC")) == 0) && (ret == RET_OK)) {
|
||||
autpc_struct *autpc_s = (autpc_struct*)msi->priv;
|
||||
autpc_s->direct_to_dac = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t autpc_msi_del_output(struct msi *msi, const char *msi_name)
|
||||
{
|
||||
int32_t ret = RET_ERR;
|
||||
if(msi_name == NULL) {
|
||||
os_printf("autpc msi del output fail,msi_name is null\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
if(msi == NULL) {
|
||||
os_printf("autpc msi del output fail,autpc msi is null\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
ret = msi_del_output(msi, NULL, msi_name);
|
||||
if(os_strncmp(msi_name, "R_AUDAC", os_strlen("R_AUDAC")) == 0) {
|
||||
autpc_struct *autpc_s = (autpc_struct*)msi->priv;
|
||||
autpc_s->direct_to_dac = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t autpc_msi_deinit(struct msi *msi)
|
||||
{
|
||||
if(msi == NULL) {
|
||||
os_printf("autpc msi deinit fail,autpc msi is null\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
msi_destroy(msi);
|
||||
return RET_OK;
|
||||
}
|
||||
23
sdk/app/autpc_msi/autpc_msi.h
Normal file
23
sdk/app/autpc_msi/autpc_msi.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef _AUTPC_STREAM_H_
|
||||
#define _AUTPC_STREAM_H_
|
||||
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "audio_media_ctrl/audio_code_ctrl.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define AUTPC_MALLOC av_psram_malloc
|
||||
#define AUTPC_ZALLOC av_psram_zalloc
|
||||
#define AUTPC_FREE av_psram_free
|
||||
#else
|
||||
#define AUTPC_MALLOC av_malloc
|
||||
#define AUTPC_ZALLOC av_zalloc
|
||||
#define AUTPC_FREE av_free
|
||||
#endif
|
||||
|
||||
struct msi *autpc_msi_init(uint32_t samplerate, uint32_t speed, uint32_t pitch, uint32_t max_inputSamples, AUDIO_TRACK *audio_track);
|
||||
int32_t autpc_msi_add_output(struct msi *msi, const char *msi_name);
|
||||
int32_t autpc_msi_del_output(struct msi *msi, const char *msi_name);
|
||||
int32_t autpc_msi_deinit(struct msi *msi);
|
||||
|
||||
#endif
|
||||
533
sdk/app/avi_encode/avi_encode_msi.c
Normal file
533
sdk/app/avi_encode/avi_encode_msi.c
Normal file
@@ -0,0 +1,533 @@
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "fatfs/osal_file.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "stream_define.h"
|
||||
#include "video_app/file_common_api.h"
|
||||
#include "loop_record_moudle/loop_record_moudle.h"
|
||||
|
||||
void *avimuxer_init2(void *fp, uint32_t max_size, int w, int h, int frate, int gop, int h265, int sampnum);
|
||||
uint32_t avimuxer_video2(void *ctx, unsigned char *buf, int len, int key, unsigned pts, uint8_t insert);
|
||||
uint32_t avimuxer_audio2(void *ctx, unsigned char *buf, int len, int key, unsigned pts);
|
||||
void avimuxer_sync(void *ctx);
|
||||
void avimuxer_exit2(void *ctx);
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC os_malloc
|
||||
#define STREAM_LIBC_FREE os_free
|
||||
#define STREAM_LIBC_ZALLOC os_zalloc
|
||||
|
||||
#define AVI_MAX_SINGLE_SIZE (50 * 1024 * 1024) // 单个AVI文件大小
|
||||
#define AVI_LOOP_REMAIN_CAP (256) // 循环录像剩余空间控制
|
||||
|
||||
#define AVI_DIR "0:/AVI"
|
||||
#define AVI_FILE_NAME ".AVI"
|
||||
|
||||
enum
|
||||
{
|
||||
MSI_AVI_STOP = BIT(0),
|
||||
MSI_AVI_THREAD_DEAD = BIT(1),
|
||||
};
|
||||
|
||||
struct avi_encode_msi_s
|
||||
{
|
||||
struct msi *msi;
|
||||
struct os_event evt;
|
||||
void *loop; // 循环录像的句柄,定时检查是否足够空间以及是否需要删除文件
|
||||
uint16_t filter_type;
|
||||
uint8_t rec_time;
|
||||
};
|
||||
|
||||
static void *creat_avi_file(void **loop, char *file_name)
|
||||
{
|
||||
void *fp = NULL;
|
||||
void *node = NULL;
|
||||
char *dir_path;
|
||||
char file_path[64];
|
||||
char sub_path[32];
|
||||
uint32_t sd_cap = 0;
|
||||
int res = 0;
|
||||
uint8_t changeflag = 0;
|
||||
uint32_t file_size = 0;
|
||||
|
||||
res = osal_fatfsfree("0:", NULL, &sd_cap);
|
||||
os_printf(KERN_INFO "sd_cap: %d\n", sd_cap);
|
||||
if (res != 0 || sd_cap == 0)
|
||||
{
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
|
||||
get_node:
|
||||
if (sd_cap < AVI_LOOP_REMAIN_CAP)
|
||||
{
|
||||
if (!*loop)
|
||||
{
|
||||
*loop = get_file_list(AVI_DIR, AVI_FILE_NAME);
|
||||
}
|
||||
|
||||
if (*loop)
|
||||
{
|
||||
node = get_file_node(*loop);
|
||||
if (!node)
|
||||
{
|
||||
free_file_list(*loop);
|
||||
*loop = get_file_list(AVI_DIR, AVI_FILE_NAME);
|
||||
if (!*loop)
|
||||
{
|
||||
_os_printf("%s %d\r\n", __FUNCTION__, __LINE__);
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
node = get_file_node(*loop);
|
||||
}
|
||||
while (!node)
|
||||
{
|
||||
dir_path = get_file_dir(*loop);
|
||||
res = osal_unlink_dir(dir_path, 0);
|
||||
if (res != FR_OK)
|
||||
{
|
||||
_os_printf("unlink dir %s err, res: %d\r\n", dir_path, res);
|
||||
res = osal_unlink_dir(dir_path, 1);
|
||||
if (res != FR_OK)
|
||||
{
|
||||
_os_printf("%s %d, force unlink dir %s err, res: %d\r\n", __FUNCTION__, __LINE__, dir_path, res);
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
_os_printf("force unlink dir %s\r\n", dir_path);
|
||||
}
|
||||
_os_printf("unlink dir %s\r\n", dir_path);
|
||||
free_file_list(*loop);
|
||||
*loop = get_file_list(AVI_DIR, AVI_FILE_NAME);
|
||||
if (!*loop)
|
||||
{
|
||||
_os_printf("%s %d\r\n", __FUNCTION__, __LINE__);
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
node = get_file_node(*loop);
|
||||
if (node)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
file_size = get_file_size(node);
|
||||
if (file_size < AVI_MAX_SINGLE_SIZE)
|
||||
{
|
||||
char path[64];
|
||||
char *name = get_file_name(node);
|
||||
dir_path = get_file_dir(*loop);
|
||||
os_sprintf(path, "%s/%s", dir_path, name);
|
||||
res = osal_unlink(path);
|
||||
if (res == FR_OK)
|
||||
{
|
||||
_os_printf("unlink file %s, filesize: %d\r\n", path, file_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
_os_printf("%s %d\tunlink file %s fail, res: %d\r\n", __FUNCTION__, __LINE__, path, res);
|
||||
}
|
||||
free_file_node(node);
|
||||
node = NULL;
|
||||
goto get_node;
|
||||
}
|
||||
changeflag = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_os_printf("%s %d\r\n", __FUNCTION__, __LINE__);
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
}
|
||||
|
||||
if (get_extension_file_name(AVI_DIR, sub_path, file_name, AVI_FILE_NAME))
|
||||
{
|
||||
_os_printf("%s %d\tget_avi_file_name fail\r\n", __FUNCTION__, __LINE__);
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
os_sprintf(file_path, "%s/%s", sub_path, file_name);
|
||||
os_printf(KERN_INFO "avi file_path: %s\r\n", file_path);
|
||||
|
||||
void *sub_dir = osal_opendir(sub_path);
|
||||
if (!sub_dir)
|
||||
{
|
||||
res = osal_fmkdir(sub_path);
|
||||
if (res != FR_OK)
|
||||
{
|
||||
if (res == FR_DENIED)
|
||||
{
|
||||
char path[64];
|
||||
char *name = get_file_name(node);
|
||||
dir_path = get_file_dir(*loop);
|
||||
os_sprintf(path, "%s/%s", dir_path, name);
|
||||
res = osal_unlink(path);
|
||||
if (res != FR_OK)
|
||||
{
|
||||
_os_printf("%s %d\tunlink file %s fail, res: %d\r\n", __FUNCTION__, __LINE__, path, res);
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
_os_printf("unlink file %s\r\n", path);
|
||||
free_file_node(node);
|
||||
node = NULL;
|
||||
res = osal_fmkdir(sub_path);
|
||||
if (res == FR_OK)
|
||||
{
|
||||
goto get_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
_os_printf("%s %d\tmkdir %s fail, res: %d\r\n", __FUNCTION__, __LINE__, sub_path, res);
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
}
|
||||
_os_printf("mkdir %s err, create rec dir\r\n", sub_path);
|
||||
|
||||
void *rec_dir = osal_opendir(AVI_DIR);
|
||||
if (!rec_dir)
|
||||
{
|
||||
res = osal_fmkdir(AVI_DIR);
|
||||
if (res != FR_OK)
|
||||
{
|
||||
_os_printf("%s %d\tmkdir %s fail, res: %d\r\n", __FUNCTION__, __LINE__, AVI_DIR, res);
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = osal_fmkdir(sub_path);
|
||||
if (res != FR_OK)
|
||||
{
|
||||
_os_printf("%s %d\tmkdir %s fail, res: %d\r\n", __FUNCTION__, __LINE__, sub_path, res);
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osal_closedir(rec_dir);
|
||||
_os_printf("%s %d\tmkdir %s fail, res: %d\r\n", __FUNCTION__, __LINE__, sub_path, res);
|
||||
goto creat_avi_file_end;
|
||||
}
|
||||
}
|
||||
_os_printf("mkdir %s\r\n", sub_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
osal_closedir(sub_dir);
|
||||
}
|
||||
|
||||
if (changeflag)
|
||||
{
|
||||
char old_filepath[64];
|
||||
char *name = get_file_name(node);
|
||||
dir_path = get_file_dir(*loop);
|
||||
os_sprintf(old_filepath, "%s/%s", dir_path, name);
|
||||
res = osal_rename(old_filepath, file_path);
|
||||
if (res != FR_OK)
|
||||
{
|
||||
_os_printf("rename file %s err, res: %d\r\n", old_filepath, res);
|
||||
if (sd_cap < AVI_LOOP_REMAIN_CAP)
|
||||
{
|
||||
_os_printf("%s %d\tsd_cap: %d\r\n", __FUNCTION__, __LINE__, sd_cap);
|
||||
free_file_node(node);
|
||||
node = NULL;
|
||||
goto get_node;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_os_printf("rename file %s to %s\r\n", old_filepath, file_path);
|
||||
}
|
||||
|
||||
#if 0
|
||||
char thumb_path[64];
|
||||
gen_thumb_path(name, thumb_path, sizeof(thumb_path));
|
||||
res = osal_unlink(thumb_path);
|
||||
if (res != FR_OK) {
|
||||
_os_printf("unlink thumb_path %s err, res: %d\r\n", thumb_path, res);
|
||||
} else {
|
||||
_os_printf("unlink thumb_path: %s\r\n", thumb_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
free_file_node(node);
|
||||
node = NULL;
|
||||
|
||||
char *min_file = get_min_file(*loop);
|
||||
if (min_file && (os_strcmp(file_name, min_file) < 0))
|
||||
{
|
||||
free_file_list(*loop);
|
||||
*loop = NULL;
|
||||
_os_printf("%s %d\tfree_file_list\r\n", __FUNCTION__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
fp = osal_fopen(file_path, "wb+");
|
||||
creat_avi_file_end:
|
||||
if (node)
|
||||
{
|
||||
free_file_node(node);
|
||||
node = NULL;
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
static int avi_encode_running(struct msi *msi, uint32_t save_time)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t res = 0;
|
||||
uint32_t AVI_status = 0;
|
||||
uint32_t write_start_time = 0;
|
||||
uint32_t sys_start_time = os_jiffies();
|
||||
uint32_t count_fps = 0;
|
||||
uint32_t audio_fps = 0;
|
||||
uint32_t last_syn_time = os_jiffies();
|
||||
uint32_t already_save_time = 0;
|
||||
uint32_t fbtime = 0;
|
||||
|
||||
struct avi_encode_msi_s *avi_encode = (struct avi_encode_msi_s *) msi->priv;
|
||||
struct framebuff *fb = NULL;
|
||||
uint32_t fps = 25;
|
||||
uint32_t fps_time = 1000 / fps;
|
||||
char filename[64];
|
||||
void *fp = creat_avi_file(&avi_encode->loop, filename);
|
||||
void *ctx = avimuxer_init2(fp, AVI_MAX_SINGLE_SIZE, 1280, 720, fps, 0, 0, 0);
|
||||
|
||||
os_printf(KERN_INFO"fp:%X\tctx:%X\n", fp, ctx);
|
||||
if (fp && ctx)
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
while (fp)
|
||||
{
|
||||
os_event_wait(&avi_encode->evt, MSI_AVI_STOP, &AVI_status, OS_EVENT_WMODE_OR, 0);
|
||||
// 结束写卡
|
||||
if (AVI_status & MSI_AVI_STOP)
|
||||
{
|
||||
ret = 1;
|
||||
os_printf("%s:%d", __FUNCTION__, __LINE__);
|
||||
goto avi_encode_thread_end;
|
||||
}
|
||||
fb = msi_get_fb(msi, 0);
|
||||
if (fb && fb->mtype == F_JPG)
|
||||
{
|
||||
if (write_start_time == 0)
|
||||
{
|
||||
write_start_time = fb->time;
|
||||
}
|
||||
count_fps++;
|
||||
_os_printf(KERN_INFO "O");
|
||||
if ((fb->time - write_start_time) / fps_time > count_fps)
|
||||
{
|
||||
uint32_t insert_num = ((fb->time - write_start_time) / fps_time) - count_fps;
|
||||
for (int i = 0; i < insert_num; i++)
|
||||
{
|
||||
res |= avimuxer_video2(ctx, fb->data, fb->len, 1, 40, 1);
|
||||
count_fps++;
|
||||
}
|
||||
}
|
||||
res |= avimuxer_video2(ctx, fb->data, fb->len, 1, 40, 0);
|
||||
fbtime = fb->time;
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
if (res || fbtime - write_start_time >= save_time)
|
||||
{
|
||||
goto avi_encode_thread_end;
|
||||
}
|
||||
}
|
||||
// 音频添加
|
||||
else if (write_start_time && fb && fb->mtype == F_AUDIO)
|
||||
{
|
||||
_os_printf(KERN_INFO "A");
|
||||
audio_fps++;
|
||||
res |= avimuxer_audio2(ctx, fb->data, fb->len, 0, 0);
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
if (res)
|
||||
{
|
||||
goto avi_encode_thread_end;
|
||||
}
|
||||
}
|
||||
else if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
// 如果系统时间超过了30s依然没有保存完成,就直接退出
|
||||
if (os_jiffies() - sys_start_time >= save_time + 30 * 1000)
|
||||
{
|
||||
goto avi_encode_thread_end;
|
||||
}
|
||||
|
||||
if (os_jiffies() - last_syn_time > 1000)
|
||||
{
|
||||
// avimuxer_sync(ctx);
|
||||
last_syn_time = os_jiffies();
|
||||
already_save_time++;
|
||||
os_printf(KERN_INFO"sync:%d %d %d\n", already_save_time, count_fps,audio_fps);
|
||||
}
|
||||
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
avi_encode_thread_end:
|
||||
os_printf(KERN_EMERG "%s:%d\tres:%d\n", __FUNCTION__, __LINE__, res);
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
|
||||
if (ctx)
|
||||
{
|
||||
avimuxer_exit2(ctx);
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
osal_fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
// os_printf("save time:%d\tv_count:%d\n",(uint32_t)os_jiffies(),v_count);
|
||||
os_printf("avi encode end\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 测试文件保存,保存一分钟吧,一直录卡,直到关闭msi
|
||||
static void avi_encode_thread(void *d)
|
||||
{
|
||||
int ret = 0;
|
||||
struct msi *msi = (struct msi *) d;
|
||||
struct avi_encode_msi_s *avi_encode = (struct avi_encode_msi_s *) msi->priv;
|
||||
|
||||
msi_get(msi);
|
||||
|
||||
while (msi)
|
||||
{
|
||||
msi->enable = 1;
|
||||
ret = avi_encode_running(msi, avi_encode->rec_time * 1000);
|
||||
msi->enable = 0;
|
||||
os_printf(KERN_EMERG "%s:%d ret:%d\tend\n", __FUNCTION__, __LINE__, ret);
|
||||
if (ret)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
os_printf("%s:%d\tret:%d\n", __FUNCTION__, __LINE__, ret);
|
||||
if (avi_encode->loop)
|
||||
{
|
||||
free_file_list(avi_encode->loop);
|
||||
avi_encode->loop = NULL;
|
||||
}
|
||||
|
||||
struct framebuff *fb;
|
||||
while (1)
|
||||
{
|
||||
fb = msi_get_fb(msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
os_event_set(&avi_encode->evt, MSI_AVI_THREAD_DEAD, NULL);
|
||||
msi_put(msi);
|
||||
os_printf("%s:%d end\n", __FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
static int32_t avi_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct avi_encode_msi_s *avi_encode = (struct avi_encode_msi_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
os_event_wait(&avi_encode->evt, MSI_AVI_THREAD_DEAD, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, -1);
|
||||
os_event_del(&avi_encode->evt);
|
||||
STREAM_LIBC_FREE(avi_encode);
|
||||
break;
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
os_event_set(&avi_encode->evt, MSI_AVI_STOP, NULL);
|
||||
break;
|
||||
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
|
||||
if (fb->mtype == F_JPG && avi_encode->filter_type != (uint16_t) ~0)
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if (avi_encode->filter_type == fb->stype)
|
||||
{
|
||||
ret = RET_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_GET_RUNNING:
|
||||
{
|
||||
uint32_t rflags = 0;
|
||||
os_event_wait(&avi_encode->evt, MSI_AVI_THREAD_DEAD | MSI_AVI_STOP, &rflags, OS_EVENT_WMODE_OR, 0);
|
||||
if (param1)
|
||||
{
|
||||
*(uint32_t *) param1 = (rflags & (MSI_AVI_THREAD_DEAD | MSI_AVI_STOP)) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *avi_encode_msi_init(const char *avi_msi_name, uint16_t filter_type, uint8_t rec_time)
|
||||
{
|
||||
struct avi_encode_msi_s *avi_encode = NULL;
|
||||
struct msi *msi = msi_new(avi_msi_name, 64, NULL);
|
||||
if (msi && !msi->priv)
|
||||
{
|
||||
avi_encode = (struct avi_encode_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct avi_encode_msi_s));
|
||||
ASSERT(avi_encode);
|
||||
avi_encode->filter_type = filter_type;
|
||||
avi_encode->rec_time = rec_time;
|
||||
msi->priv = avi_encode;
|
||||
os_event_init(&avi_encode->evt);
|
||||
avi_encode->msi = msi;
|
||||
msi->action = avi_encode_msi_action;
|
||||
msi->enable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 不要重复打开,同一个名称需要等待上一次写入完成后并且关闭后才可以重新打开
|
||||
// 因为这里new了一次,所以要destroy一次(new和destroy要配对,实际msi的destroy是在另一个地方)
|
||||
if (msi)
|
||||
{
|
||||
msi_destroy(msi);
|
||||
msi = NULL;
|
||||
goto avi_encode_msi_init_end;
|
||||
}
|
||||
}
|
||||
|
||||
void *avi_hdl = os_task_create("avi_encode", avi_encode_thread, msi, OS_TASK_PRIORITY_NORMAL, 0, NULL, 2048);
|
||||
os_printf("avi_hdl:%X\n", avi_hdl);
|
||||
if (!avi_hdl && avi_encode)
|
||||
{
|
||||
os_event_set(&avi_encode->evt, MSI_AVI_THREAD_DEAD, NULL);
|
||||
}
|
||||
avi_encode_msi_init_end:
|
||||
return msi;
|
||||
}
|
||||
9
sdk/app/avi_encode/avi_encode_msi.h
Normal file
9
sdk/app/avi_encode/avi_encode_msi.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef __AVI_ENCODE_MSI_H__
|
||||
#define __AVI_ENCODE_MSI_H__
|
||||
#include "file_process.h"
|
||||
struct msi *avi_encode_msi_init(const char *avi_msi_name, uint16_t filter_type, uint8_t rec_time);
|
||||
struct msi *avi_encode_msi2_init(const char *avi_msi_name, uint8_t srcID, uint8_t filter_type, uint8_t rec_time,
|
||||
uint32_t audio_encode, struct file_process *file_process, uint8_t mode);
|
||||
|
||||
|
||||
#endif
|
||||
392
sdk/app/avi_encode/avi_encode_msi2.c
Normal file
392
sdk/app/avi_encode/avi_encode_msi2.c
Normal file
@@ -0,0 +1,392 @@
|
||||
#include "basic_include.h"
|
||||
#include "fatfs/osal_file.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "stream_define.h"
|
||||
#include "app/video_app/file_thumb.h"
|
||||
#include "app/recorder/file_process.h"
|
||||
|
||||
void *avimuxer_init2(void *fp, uint32_t max_size, int w, int h, int frate, int gop, int h265, int sampnum);
|
||||
uint32_t avimuxer_video2(void *ctx, unsigned char *buf, int len, int key, unsigned pts, uint8_t insert);
|
||||
uint32_t avimuxer_audio2(void *ctx, unsigned char *buf, int len, int key, unsigned pts);
|
||||
void avimuxer_sync(void *ctx);
|
||||
void avimuxer_exit2(void *ctx);
|
||||
struct msi *avi_thumb_msi_init(const char *filename, uint8_t srcID, uint8_t filter);
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC os_malloc
|
||||
#define STREAM_LIBC_FREE os_free
|
||||
#define STREAM_LIBC_ZALLOC os_zalloc
|
||||
|
||||
#ifndef MAX_SINGLE_AVI_SIZE
|
||||
#define MAX_SINGLE_AVI_SIZE (100 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
MSI_AVI_START = BIT(0),
|
||||
MSI_AVI_STOP = BIT(1),
|
||||
MSI_AVI_THREAD_DEAD = BIT(2),
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
AVI_ENCODE_ERR_NONE,
|
||||
AVI_ENCODE_ERR_STOP,
|
||||
AVI_ENCODE_ERR_NO_SD,
|
||||
};
|
||||
|
||||
struct avi_encode_msi_s
|
||||
{
|
||||
struct msi *msi;
|
||||
struct os_event evt;
|
||||
struct file_process file_process;
|
||||
uint8_t filter_type;
|
||||
uint8_t rec_time;
|
||||
uint16_t rec_second;
|
||||
uint32_t file_size;
|
||||
uint32_t audio_encode;
|
||||
};
|
||||
|
||||
static int avi_encode_running(struct msi *msi, uint32_t save_time, void *fp, const char *avi_filename, uint32_t filesize)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t res = 0;
|
||||
uint32_t AVI_status = 0;
|
||||
uint32_t write_start_time = 0;
|
||||
uint32_t sys_start_time = os_jiffies();
|
||||
uint32_t count_fps = 0;
|
||||
uint32_t audio_fps = 0;
|
||||
uint32_t last_syn_time = os_jiffies();
|
||||
uint32_t already_save_time = 0;
|
||||
uint32_t fbtime = 0;
|
||||
|
||||
struct avi_encode_msi_s *avi_encode = (struct avi_encode_msi_s *) msi->priv;
|
||||
struct msi *avi_thumb_msi = NULL;
|
||||
struct framebuff *fb = NULL;
|
||||
uint32_t fps = 25;
|
||||
uint32_t fps_time = 1000 / fps;
|
||||
void *ctx = avimuxer_init2(fp, filesize, 1280, 720, fps, 0, 0, 0);
|
||||
|
||||
os_printf(KERN_INFO"fp:%X\tctx:%X\n", fp, ctx);
|
||||
if (!fp || !ctx)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
ret = AVI_ENCODE_ERR_NO_SD;
|
||||
goto avi_encode_thread_end;
|
||||
}
|
||||
|
||||
avi_thumb_msi = avi_thumb_msi_init(avi_filename, FRAMEBUFF_SOURCE_USB, FSTYPE_NONE);
|
||||
msi->enable = 1;
|
||||
|
||||
while (fp)
|
||||
{
|
||||
os_event_wait(&avi_encode->evt, MSI_AVI_STOP, &AVI_status, OS_EVENT_WMODE_OR, 0);
|
||||
// 结束写卡
|
||||
if (AVI_status & MSI_AVI_STOP)
|
||||
{
|
||||
ret = 1;
|
||||
os_printf("%s:%d", __FUNCTION__, __LINE__);
|
||||
goto avi_encode_thread_end;
|
||||
}
|
||||
fb = msi_get_fb(msi, 0);
|
||||
if (fb && fb->mtype == F_JPG)
|
||||
{
|
||||
if (write_start_time == 0)
|
||||
{
|
||||
write_start_time = fb->time;
|
||||
}
|
||||
count_fps++;
|
||||
_os_printf(KERN_INFO "O");
|
||||
if ((fb->time - write_start_time) / fps_time > count_fps)
|
||||
{
|
||||
uint32_t insert_num = ((fb->time - write_start_time) / fps_time) - count_fps;
|
||||
for (int i = 0; i < insert_num; i++)
|
||||
{
|
||||
res |= avimuxer_video2(ctx, fb->data, fb->len, 1, 40, 1);
|
||||
count_fps++;
|
||||
}
|
||||
}
|
||||
res |= avimuxer_video2(ctx, fb->data, fb->len, 1, 40, 0);
|
||||
fbtime = fb->time;
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
if (res || fbtime - write_start_time >= save_time)
|
||||
{
|
||||
goto avi_encode_thread_end;
|
||||
}
|
||||
}
|
||||
// 音频添加
|
||||
else if (avi_encode->audio_encode && write_start_time && fb && fb->mtype == F_AUDIO)
|
||||
{
|
||||
_os_printf(KERN_INFO "A");
|
||||
audio_fps++;
|
||||
res |= avimuxer_audio2(ctx, fb->data, fb->len, 0, 0);
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
if (res)
|
||||
{
|
||||
goto avi_encode_thread_end;
|
||||
}
|
||||
}
|
||||
else if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
// 如果系统时间超过了30s依然没有保存完成,就直接退出
|
||||
if (os_jiffies() - sys_start_time >= save_time + 30 * 1000)
|
||||
{
|
||||
goto avi_encode_thread_end;
|
||||
}
|
||||
|
||||
if (fbtime - last_syn_time > 1000)
|
||||
{
|
||||
// avimuxer_sync(ctx);
|
||||
last_syn_time = fbtime;
|
||||
already_save_time = fbtime - write_start_time;
|
||||
avi_encode->rec_second = already_save_time / 1000;
|
||||
os_printf(KERN_INFO"sync:%d %d %d\n", already_save_time, count_fps, audio_fps);
|
||||
}
|
||||
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
avi_encode_thread_end:
|
||||
|
||||
avi_encode->rec_second = 0;
|
||||
|
||||
os_printf(KERN_EMERG "%s:%d\tres:%d\n", __FUNCTION__, __LINE__, res);
|
||||
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
|
||||
if (ctx)
|
||||
{
|
||||
avimuxer_exit2(ctx);
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
osal_fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
if (avi_thumb_msi)
|
||||
{
|
||||
msi_destroy(avi_thumb_msi);
|
||||
}
|
||||
|
||||
// os_printf("save time:%d\tv_count:%d\n",(uint32_t)os_jiffies(),v_count);
|
||||
os_printf("avi encode end\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 测试文件保存,保存一分钟吧,一直录卡,直到关闭msi
|
||||
static void avi_encode_thread(void *d)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t avi_status = 0;
|
||||
struct msi *msi = (struct msi *) d;
|
||||
struct avi_encode_msi_s *avi_encode = (struct avi_encode_msi_s *) msi->priv;
|
||||
struct file_process *file_process = &avi_encode->file_process;
|
||||
void *fp = NULL;
|
||||
char filename[64];
|
||||
char filepath[64];
|
||||
uint32_t filesize = 0;
|
||||
|
||||
msi_get(msi);
|
||||
os_event_wait(&avi_encode->evt, MSI_AVI_START, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, -1);
|
||||
|
||||
while(msi)
|
||||
{
|
||||
filesize = avi_encode->rec_time * avi_encode->file_size;
|
||||
if(file_process->create_file)
|
||||
{
|
||||
fp = file_process->create_file(file_process, filename, filepath, filesize);
|
||||
}
|
||||
ret = avi_encode_running(msi, avi_encode->rec_time * 60 * 1000, fp, filename, filesize);
|
||||
msi->enable = 0;
|
||||
if(file_process->lock_file && ret != 2)
|
||||
{
|
||||
file_process->lock_file(filename, filepath);
|
||||
}
|
||||
|
||||
os_printf(KERN_EMERG "%s %d end\n", __FUNCTION__, __LINE__);
|
||||
if (ret)
|
||||
{
|
||||
if (file_process->loop_free)
|
||||
{
|
||||
file_process->loop_free(&file_process->loop);
|
||||
}
|
||||
if(ret == AVI_ENCODE_ERR_NO_SD)
|
||||
{
|
||||
avi_status = 0;
|
||||
os_event_wait(&avi_encode->evt, MSI_AVI_STOP, &avi_status, OS_EVENT_WMODE_OR, 1000);
|
||||
if(avi_status & MSI_AVI_STOP)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os_printf(KERN_DEBUG "%s %d end, ret:%d\n", __FUNCTION__, __LINE__, ret);
|
||||
|
||||
struct framebuff *fb;
|
||||
while (1)
|
||||
{
|
||||
fb = msi_get_fb(msi, 0);
|
||||
if (fb)
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
os_event_set(&avi_encode->evt, MSI_AVI_THREAD_DEAD, NULL);
|
||||
msi_put(msi);
|
||||
os_printf("%s:%d end\n", __FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
static int32_t avi_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct avi_encode_msi_s *avi_encode = (struct avi_encode_msi_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
os_event_wait(&avi_encode->evt, MSI_AVI_THREAD_DEAD, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, -1);
|
||||
os_event_del(&avi_encode->evt);
|
||||
STREAM_LIBC_FREE(avi_encode);
|
||||
break;
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
os_event_set(&avi_encode->evt, MSI_AVI_STOP, NULL);
|
||||
break;
|
||||
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
|
||||
if (fb->mtype == F_JPG && avi_encode->filter_type != (uint8_t) ~0)
|
||||
{
|
||||
ret = RET_ERR;
|
||||
if (avi_encode->filter_type == fb->stype)
|
||||
{
|
||||
ret = RET_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_GET_RUNNING:
|
||||
{
|
||||
uint32_t rflags = 0;
|
||||
os_event_wait(&avi_encode->evt, MSI_AVI_THREAD_DEAD | MSI_AVI_STOP, &rflags, OS_EVENT_WMODE_OR, 0);
|
||||
if (param1)
|
||||
{
|
||||
*(uint32_t *) param1 = (rflags & (MSI_AVI_THREAD_DEAD | MSI_AVI_STOP)) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_MEDIA_CTRL:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
uint32_t arg = (uint32_t) param2;
|
||||
switch(cmd_self)
|
||||
{
|
||||
case MSI_MEDIA_CTRL_GET_RECTIME:
|
||||
*(uint32_t *) arg = avi_encode->rec_second;
|
||||
break;
|
||||
case MSI_MEDIA_CTRL_RECORD_START:
|
||||
os_event_set(&avi_encode->evt, MSI_AVI_START, NULL);
|
||||
break;
|
||||
case MSI_MEDIA_CTRL_SET_RECORD_SIZE:
|
||||
avi_encode->file_size = arg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *avi_encode_msi2_init(const char *avi_msi_name, uint8_t srcID, uint8_t filter_type, uint8_t rec_time,
|
||||
uint32_t audio_encode, struct file_process *file_process, uint8_t mode)
|
||||
{
|
||||
uint8_t is_new = 0;
|
||||
struct avi_encode_msi_s *avi_encode = NULL;
|
||||
struct msi *msi = msi_new(avi_msi_name, 64, &is_new);
|
||||
(void) srcID;
|
||||
(void) mode;
|
||||
if (is_new)
|
||||
{
|
||||
avi_encode = (struct avi_encode_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct avi_encode_msi_s));
|
||||
ASSERT(avi_encode);
|
||||
avi_encode->filter_type = filter_type;
|
||||
avi_encode->rec_time = rec_time;
|
||||
avi_encode->file_size = MAX_SINGLE_AVI_SIZE;
|
||||
if(file_process == NULL)
|
||||
{
|
||||
// 配置默认值
|
||||
avi_encode->file_process.loop = NULL;
|
||||
avi_encode->file_process.rec_path = REC_PATH;
|
||||
avi_encode->file_process.ext_name = AVI_EXTENSION_NAME;
|
||||
avi_encode->file_process.create_file = rec_create_file;
|
||||
avi_encode->file_process.loop_free = rec_loop_free;
|
||||
avi_encode->file_process.lock_file = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
os_memcpy(&avi_encode->file_process, file_process, sizeof(struct file_process));
|
||||
}
|
||||
|
||||
avi_encode->audio_encode = audio_encode;
|
||||
msi->priv = avi_encode;
|
||||
os_event_init(&avi_encode->evt);
|
||||
avi_encode->msi = msi;
|
||||
msi->action = avi_encode_msi_action;
|
||||
msi->enable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 不要重复打开,同一个名称需要等待上一次写入完成后并且关闭后才可以重新打开
|
||||
// 因为这里new了一次,所以要destroy一次(new和destroy要配对,实际msi的destroy是在另一个地方)
|
||||
if (msi)
|
||||
{
|
||||
msi_destroy(msi);
|
||||
msi = NULL;
|
||||
}
|
||||
goto avi_encode_msi_init_end;
|
||||
}
|
||||
|
||||
void *avi_hdl = os_task_create("avi_encode", avi_encode_thread, msi, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 2048);
|
||||
os_printf("avi_hdl:%X\n", avi_hdl);
|
||||
if (!avi_hdl && avi_encode)
|
||||
{
|
||||
os_event_set(&avi_encode->evt, MSI_AVI_THREAD_DEAD, NULL);
|
||||
}
|
||||
avi_encode_msi_init_end:
|
||||
return msi;
|
||||
}
|
||||
852
sdk/app/babyprotocol/babyprotocol_client_h264.c
Normal file
852
sdk/app/babyprotocol/babyprotocol_client_h264.c
Normal file
@@ -0,0 +1,852 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "syscfg.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "netif/ethernetif.h"
|
||||
#include "stream_define.h"
|
||||
#include "stream_frame.h"
|
||||
#include "babyprotocol_h264.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "lib/video/h264/h264_drv.h"
|
||||
#include "hal/vpp.h"
|
||||
#include "lib/umac/ieee80211.h"
|
||||
|
||||
#ifdef SYS_APP_BBM_CAM
|
||||
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
|
||||
#define MAX_USER_VIDEO_TX 16
|
||||
#define MAX_VIDEO_PKT_LEN 1430
|
||||
|
||||
frame_msg client_frame;
|
||||
uint32_t client_dev_magic = 0;
|
||||
os_mutex_t thread_lock;
|
||||
|
||||
static struct os_semaphore net_h264_sem = {0,NULL};
|
||||
static struct os_semaphore net_h264_status_sem = {0,NULL};
|
||||
static struct os_semaphore net_tcp_sem = {0,NULL};
|
||||
|
||||
static k_task_handle_t handle_task_recv;
|
||||
static k_task_handle_t handle_data_task_recv;
|
||||
static k_task_handle_t handle_tcp_task_recv;
|
||||
|
||||
static int handle_protocol_fd = - 1;
|
||||
static int handle_data_protocol_fd = - 1;
|
||||
static int tcp_connect_fd = -1;
|
||||
static volatile uint32 status_unlock = 0;
|
||||
|
||||
static in_addr_t client_addr = 0;
|
||||
uint8_t photo_buf[1440] __attribute__ ((aligned(4)));;
|
||||
uint8_t server_staus_buf[200];
|
||||
volatile uint32 server_frame_rate;
|
||||
|
||||
uint32_t heartbeat = 0;
|
||||
|
||||
EVT_HDL tcp_read_ev;
|
||||
|
||||
static uint8_t src_filter_type = FSTYPE_H264_GEN420_DATA;
|
||||
|
||||
void net_h264_status_sema_init()
|
||||
{
|
||||
os_sema_init(&net_h264_status_sem,0);
|
||||
}
|
||||
|
||||
int32 net_h264_status_sema_down(int32 tmo_ms)
|
||||
{
|
||||
return os_sema_down(&net_h264_status_sem,tmo_ms);
|
||||
}
|
||||
|
||||
void net_h264_status_sema_up()
|
||||
{
|
||||
os_sema_up(&net_h264_status_sem);
|
||||
}
|
||||
|
||||
void net_h264_sema_init()
|
||||
{
|
||||
os_sema_init(&net_h264_sem,0);
|
||||
}
|
||||
|
||||
void net_h264_sema_down(int32 tmo_ms)
|
||||
{
|
||||
os_sema_down(&net_h264_sem,tmo_ms);
|
||||
}
|
||||
|
||||
void net_h264_sema_up()
|
||||
{
|
||||
os_sema_up(&net_h264_sem);
|
||||
}
|
||||
|
||||
void net_tcp_sema_init()
|
||||
{
|
||||
os_sema_init(&net_tcp_sem,0);
|
||||
}
|
||||
|
||||
int32 net_tcp_sema_down(int32 tmo_ms)
|
||||
{
|
||||
return os_sema_down(&net_tcp_sem,tmo_ms);
|
||||
}
|
||||
|
||||
void net_tcp_sema_up()
|
||||
{
|
||||
os_sema_up(&net_tcp_sem);
|
||||
}
|
||||
uint16_t w_gol,h_gol;
|
||||
static int net_video_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
static uint16_t oldw = 0;
|
||||
struct fb_h264_s *h264;
|
||||
int ret = RET_OK;
|
||||
switch (cmd_id)
|
||||
{
|
||||
|
||||
// 暂时没有考虑释放
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
}
|
||||
break;
|
||||
// 接收,判断是否已经压缩了
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
if(src_filter_type != FSTYPE_H264_FILE) {
|
||||
if(oldw != w_gol){
|
||||
h264 = (struct fb_h264_s *)fb->priv; //切换分辨率时要以I帧为基础
|
||||
if(h264->type == 1){
|
||||
oldw = w_gol;
|
||||
}
|
||||
}
|
||||
|
||||
if(oldw == 1280) {
|
||||
src_filter_type = FSTYPE_H264_VPP_DATA0;
|
||||
}
|
||||
else {
|
||||
src_filter_type = FSTYPE_H264_GEN420_DATA;
|
||||
}
|
||||
}
|
||||
if(fb->stype != src_filter_type)
|
||||
{
|
||||
ret = RET_ERR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usr_protocol_create_server(uint16_t port)
|
||||
{
|
||||
int socket_c, err;
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_len = sizeof(struct sockaddr_in);
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = htons(INADDR_ANY);
|
||||
|
||||
socket_c = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket_c < 0)
|
||||
{
|
||||
printf("get socket err");
|
||||
return - 1;
|
||||
}
|
||||
|
||||
err = bind(socket_c, (struct sockaddr*) &addr, sizeof(struct sockaddr_in));
|
||||
|
||||
if (err == - 1)
|
||||
{
|
||||
close(socket_c);
|
||||
return - 1;
|
||||
|
||||
}
|
||||
return socket_c;
|
||||
}
|
||||
|
||||
void recfg_babymonitor_msg(uint8_t success){
|
||||
static uint8_t did = 0;
|
||||
static uint16_t last_still = 0;
|
||||
static uint16_t last_move = 0;
|
||||
uint16_t max_still;
|
||||
uint16_t max_move;
|
||||
static uint8_t success_frame_num = 0;
|
||||
#if 0
|
||||
static uint8_t framecnt = 0;
|
||||
static uint32_t timeout = 0;
|
||||
static uint8_t lost_frame_num = 0;
|
||||
static uint8_t speed_level = 0;
|
||||
static uint8_t last_speed_level = 0xff;
|
||||
static uint8_t success_frame_num = 0;
|
||||
|
||||
if(framecnt > 15){ //15帧内丢帧比例
|
||||
if((os_jiffies() - timeout) > 1000){ //如果刚调整过mclk,那等3秒后再进行下次调整
|
||||
if(lost_frame_num > 12){
|
||||
timeout = os_jiffies();
|
||||
speed_level = 3;
|
||||
}else if(lost_frame_num > 6){ //15帧丢了6帧以上
|
||||
timeout = os_jiffies();
|
||||
speed_level = 2;
|
||||
}else if(lost_frame_num > 3){ //15帧丢了3帧以上
|
||||
timeout = os_jiffies();
|
||||
speed_level = 1;
|
||||
}else if(lost_frame_num == 0){ //没丢帧
|
||||
if(speed_level == 0){
|
||||
speed_level = 0;
|
||||
}else{
|
||||
speed_level--;
|
||||
}
|
||||
}
|
||||
|
||||
if(last_speed_level != speed_level){
|
||||
last_speed_level = speed_level;
|
||||
|
||||
babymsg.speed = speed_level;
|
||||
}
|
||||
}
|
||||
framecnt = 0;
|
||||
lost_frame_num = 0;
|
||||
success_frame_num = 0;
|
||||
}else{
|
||||
if(success){
|
||||
success_frame_num++;
|
||||
}else{
|
||||
lost_frame_num++;
|
||||
}
|
||||
framecnt++;
|
||||
}
|
||||
babymsg.speed = speed_level;
|
||||
#else
|
||||
if(success == 0){
|
||||
success_frame_num = 0;
|
||||
if(w_gol == 1280){
|
||||
did = 1;
|
||||
}else{
|
||||
did = 2;
|
||||
}
|
||||
|
||||
if(did == 1){
|
||||
max_still = MAIN_SENSOR_STILL_MAX;
|
||||
max_move = MAIN_SENSOR_MOVE_MAX;
|
||||
}else{
|
||||
max_still = SEC_SENSOR_STILL_MAX;
|
||||
max_move = SEC_SENSOR_MOVE_MAX;
|
||||
}
|
||||
|
||||
if(last_still == 0){
|
||||
last_still = max_still;
|
||||
last_move = max_move;
|
||||
}
|
||||
|
||||
if(did == 1){
|
||||
if(last_still > MAIN_SENSOR_STILL_MIN){
|
||||
last_still = last_still - BPS_STEP;
|
||||
last_move = last_move - BPS_STEP;
|
||||
}else{
|
||||
last_still = MAIN_SENSOR_STILL_MIN;
|
||||
last_move = MAIN_SENSOR_MOVE_MIN;
|
||||
}
|
||||
}else{
|
||||
if(last_still > SEC_SENSOR_STILL_MIN){
|
||||
last_still = last_still - BPS_STEP;
|
||||
last_move = last_move - BPS_STEP;
|
||||
}else{
|
||||
last_still = SEC_SENSOR_STILL_MIN;
|
||||
last_move = SEC_SENSOR_MOVE_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
h264_recfg_bsp(did,last_move,last_still);
|
||||
h264_reflash_new_gop(did,1);
|
||||
|
||||
}else{
|
||||
success_frame_num++;
|
||||
if(success_frame_num == UP_BPS_FRM_NUM){
|
||||
if(w_gol == 1280){
|
||||
did = 1;
|
||||
}else{
|
||||
did = 2;
|
||||
}
|
||||
|
||||
success_frame_num = 0;
|
||||
|
||||
if(did == 1){
|
||||
if(last_still < MAIN_SENSOR_STILL_MAX){
|
||||
last_still = last_still + BPS_STEP;
|
||||
last_move = last_move + BPS_STEP;
|
||||
}else{
|
||||
last_still = MAIN_SENSOR_STILL_MAX;
|
||||
last_move = MAIN_SENSOR_MOVE_MAX;
|
||||
}
|
||||
}else{
|
||||
if(last_still < SEC_SENSOR_STILL_MAX){
|
||||
last_still = last_still + BPS_STEP;
|
||||
last_move = last_move + BPS_STEP;
|
||||
}else{
|
||||
last_still = SEC_SENSOR_STILL_MAX;
|
||||
last_move = SEC_SENSOR_MOVE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
h264_recfg_bsp(did,last_move,last_still);
|
||||
h264_reflash_new_gop(did,1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void udp_handle_client_status_write_workqueue(void *ei, void *d){
|
||||
int tos;
|
||||
static uint8_t pri_inv = 0;
|
||||
uint32 ie;
|
||||
status_msg *msg_head;
|
||||
char buf[12];
|
||||
int len;
|
||||
msg_head = (status_msg *)buf;
|
||||
msg_head->framenum = client_frame.framenum;
|
||||
msg_head->type = 1;
|
||||
if(client_frame.lost_num != 0){
|
||||
pri_inv++;
|
||||
if((pri_inv%2)==1){
|
||||
tos = IPTOS_PREC_NETCONTROL; // 最高优先级
|
||||
setsockopt(handle_protocol_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
|
||||
}
|
||||
len = sendto(handle_protocol_fd, (char*)buf, 2, MSG_DONTWAIT, (struct sockaddr *)d, sizeof(struct sockaddr));
|
||||
tos = IPTOS_PREC_ROUTINE; // 最低优先级
|
||||
setsockopt(handle_protocol_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
|
||||
BABY_DBG("W");
|
||||
}else{
|
||||
ie = disable_irq();
|
||||
if(status_unlock){
|
||||
status_unlock = 0;
|
||||
net_h264_status_sema_up();
|
||||
}
|
||||
enable_irq(ie);
|
||||
client_frame.status = 2; //已经收到完整数据,没必要重发,只修改状态就可以
|
||||
}
|
||||
}
|
||||
|
||||
void udp_handle_client_status_read_workqueue(){
|
||||
int retval;
|
||||
int ret;
|
||||
uint32 ie;
|
||||
uint8_t itk;
|
||||
uint8_t new_status;
|
||||
status_msg *msg_head;
|
||||
|
||||
struct sockaddr remote_addr;
|
||||
retval = 16;
|
||||
ret = recvfrom (handle_protocol_fd, server_staus_buf, 200, 0, &remote_addr, (socklen_t*)&retval);
|
||||
|
||||
os_mutex_lock(&thread_lock, osWaitForever);
|
||||
msg_head = (status_msg *)server_staus_buf;
|
||||
new_status = client_frame.status;
|
||||
client_frame.status = 2;
|
||||
|
||||
if(msg_head->framenum != client_frame.framenum){
|
||||
client_frame.status = new_status;
|
||||
os_mutex_unlock(&thread_lock);
|
||||
BABY_DBG("E(%d)",msg_head->framenum);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BABY_DBG("server recv:%d type:%d\r\n",msg_head->framenum,msg_head->type);
|
||||
|
||||
if(msg_head->type == 0){
|
||||
client_frame.lost_num = 0;
|
||||
}else if(msg_head->type == 2){
|
||||
client_frame.lost_num = ret - 2;
|
||||
memset(client_frame.lost_packet,0xff,100);
|
||||
for(itk = 0;itk < client_frame.lost_num;itk++){
|
||||
client_frame.lost_packet[itk] = server_staus_buf[2+itk];
|
||||
}
|
||||
client_frame.status = 3;
|
||||
}
|
||||
os_mutex_unlock(&thread_lock);
|
||||
|
||||
ie = disable_irq();
|
||||
if(status_unlock){
|
||||
status_unlock = 0;
|
||||
net_h264_status_sema_up();
|
||||
}
|
||||
enable_irq(ie);
|
||||
}
|
||||
|
||||
void udp_handle_client_status_thread()
|
||||
{
|
||||
uint32 ie;
|
||||
uint8_t loop_run;
|
||||
uint16_t port = 6003;
|
||||
uint8_t framenum;
|
||||
uint32_t start_tmr = 0;
|
||||
struct sockaddr_in addrServer;
|
||||
memset(&addrServer,0,sizeof(struct sockaddr_in));
|
||||
while(client_addr == 0){
|
||||
os_sleep_ms(100);
|
||||
}
|
||||
addrServer.sin_family=AF_INET;
|
||||
addrServer.sin_addr.s_addr=client_addr;//inet_addr("192.168.169.100");
|
||||
addrServer.sin_port=htons(6003);
|
||||
|
||||
handle_protocol_fd = usr_protocol_create_server(port);
|
||||
eloop_add_fd( handle_protocol_fd, EVENT_READ, EVENT_F_ENABLED, udp_handle_client_status_read_workqueue, 0 );
|
||||
while(1){
|
||||
// _os_printf("D");
|
||||
net_h264_sema_down(-1); //wait for data send finish
|
||||
BABY_DBG("Q(%d)",client_frame.status);
|
||||
start_tmr = client_frame.time;
|
||||
framenum = client_frame.framenum;
|
||||
os_sleep_ms(client_frame.timeout);
|
||||
loop_run = 0;
|
||||
while((client_frame.status == 0)&&(framenum == client_frame.framenum)){ //如果当前frame还处于等待client状态的情况,发送请求状态的要求
|
||||
eloop_add_alarm(os_jiffies(),EVENT_F_ENABLED,udp_handle_client_status_write_workqueue,(void *)&addrServer); //eventloop send
|
||||
//client_frame.timeout = 5; //5ms都读不到对回复的状态,重发吧
|
||||
os_sleep_ms(10);
|
||||
loop_run++;
|
||||
if(loop_run > 12) //重发8次后还是读不到状态,认命吧,你掉线了
|
||||
break;
|
||||
}
|
||||
|
||||
if(client_frame.status == 0){
|
||||
if(client_frame.framenum == framenum){ //要是新的frame来了,表示旧的frame已经正常结束,否则要唤醒当前帧
|
||||
ie = disable_irq();
|
||||
if(status_unlock){
|
||||
status_unlock = 0;
|
||||
net_h264_status_sema_up();
|
||||
}
|
||||
client_frame.status = 3; //frame timeout,lost
|
||||
enable_irq(ie);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void udp_handle_client_data_thread(){
|
||||
// uint8_t loop_run;
|
||||
int32 ret;
|
||||
uint32 ie;
|
||||
uint8_t framesuc = 0;
|
||||
// int init_count = 0;
|
||||
// void *priv;
|
||||
uint16_t port = 6002;
|
||||
uint8_t framenum;
|
||||
uint8_t oldcount = 0;
|
||||
uint8_t lostframe = 0;
|
||||
uint8_t itk;
|
||||
uint8_t lostidx = 0;
|
||||
uint8_t lostloop = 0;
|
||||
uint32_t framelen = 0;
|
||||
uint32_t datoffset = 0;
|
||||
uint32_t sendlen = 0;
|
||||
uint8_t pktcnt = 0;
|
||||
struct fb_h264_s *h264;
|
||||
// uint32_t start_tmr = 0;
|
||||
struct sockaddr_in addrServer;
|
||||
struct framebuff *h264_fb = NULL;
|
||||
int len;
|
||||
data_head *data_head_msg;
|
||||
struct msi *msi;
|
||||
uint32_t nal_reserve = 0;
|
||||
|
||||
msi = msi_new("NET_H264", MAX_USER_VIDEO_TX, NULL);
|
||||
msi->action = net_video_msi_action;
|
||||
msi->enable = 1;
|
||||
|
||||
while(client_addr == 0){
|
||||
os_sleep_ms(100);
|
||||
}
|
||||
framenum = 0;
|
||||
memset(&addrServer,0,sizeof(struct sockaddr_in));
|
||||
addrServer.sin_family=AF_INET;
|
||||
addrServer.sin_addr.s_addr=client_addr;//inet_addr("192.168.169.100");
|
||||
addrServer.sin_port=htons(6002);
|
||||
handle_data_protocol_fd = usr_protocol_create_server(port);
|
||||
data_head_msg = (data_head *)photo_buf;
|
||||
while(1){
|
||||
h264_fb = msi_get_fb(msi, 0);
|
||||
if (h264_fb){
|
||||
os_mutex_lock(&thread_lock, osWaitForever);
|
||||
h264 = (struct fb_h264_s *)h264_fb->priv;
|
||||
memset(data_head_msg,0,sizeof(data_head));
|
||||
data_head_msg->framenum = framenum;
|
||||
framenum++;
|
||||
data_head_msg->cnt = (h264_fb->len+MAX_VIDEO_PKT_LEN-1)/MAX_VIDEO_PKT_LEN;
|
||||
data_head_msg->frmtype = h264->type;
|
||||
framelen = h264_fb->len;
|
||||
BABY_DBG("((%d)%d %d %d)",client_dev_magic,data_head_msg->framenum,h264->type,framelen);
|
||||
|
||||
client_frame.framenum = data_head_msg->framenum;
|
||||
client_frame.status = 0;
|
||||
|
||||
os_mutex_unlock(&thread_lock);
|
||||
|
||||
if(lostframe == 1){ //lost frame ,need to wait the I frame for re-send
|
||||
if(h264->type != 1){
|
||||
goto delete_frame;
|
||||
}
|
||||
}
|
||||
|
||||
if((oldcount + 1) != h264->count){
|
||||
if((h264->count == 0)&&(oldcount == 255)){
|
||||
if(lostframe == 1){
|
||||
if(h264->type != 1){
|
||||
BABY_DBG("send slow,lost frame wait i frame\r\n");
|
||||
goto delete_frame;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(h264->type == 1){
|
||||
BABY_DBG("frame lost ,but this frame is i frame ,send it\r\n");
|
||||
}else{
|
||||
BABY_DBG("send slow ,lost frame ,wait I frame:%d %d\r\n",oldcount,h264->count);
|
||||
h264_reflash_new_gop(1,1);
|
||||
lostframe = 1;
|
||||
goto delete_frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lostframe = 0;
|
||||
|
||||
pktcnt = 0;
|
||||
datoffset = 0;
|
||||
|
||||
client_frame.lost_num = data_head_msg->cnt;
|
||||
framesuc = 1;
|
||||
nal_reserve = 0;
|
||||
if(h264_fb->stype == FSTYPE_H264_FILE) {
|
||||
if(h264->type == 1) {
|
||||
nal_reserve = h264->pps_len + h264->sps_len + 12;
|
||||
}
|
||||
else if(h264->type == 2) {
|
||||
nal_reserve = 4;
|
||||
}
|
||||
}
|
||||
while(framelen != 0){
|
||||
data_head_msg->pack = pktcnt;
|
||||
if(nal_reserve > 0) {
|
||||
if(h264->type == 1) {
|
||||
*((uint32_t*)(photo_buf+sizeof(data_head))) = 0x1000000;
|
||||
os_memcpy(photo_buf+sizeof(data_head)+4, h264->sps, h264->sps_len);
|
||||
*((uint32_t*)(photo_buf+sizeof(data_head)+h264->sps_len+4)) = 0x1000000;
|
||||
os_memcpy(photo_buf+sizeof(data_head)+h264->sps_len+8, h264->pps, h264->pps_len);
|
||||
*((uint32_t*)(photo_buf+sizeof(data_head)+h264->pps_len+h264->sps_len+8)) = 0x1000000;
|
||||
}
|
||||
else {
|
||||
*((uint32_t*)(photo_buf+sizeof(data_head))) = 0x1000000;
|
||||
}
|
||||
}
|
||||
if(framelen >= (MAX_VIDEO_PKT_LEN - nal_reserve)){
|
||||
framelen = framelen - (MAX_VIDEO_PKT_LEN-nal_reserve);
|
||||
memcpy(photo_buf+sizeof(data_head)+nal_reserve,h264_fb->data+datoffset,(MAX_VIDEO_PKT_LEN-nal_reserve));
|
||||
datoffset += (MAX_VIDEO_PKT_LEN-nal_reserve);
|
||||
sendlen = MAX_VIDEO_PKT_LEN;
|
||||
}else{
|
||||
memcpy(photo_buf+sizeof(data_head)+nal_reserve,h264_fb->data+datoffset,framelen);
|
||||
sendlen = framelen + nal_reserve;
|
||||
framelen = 0;
|
||||
}
|
||||
if(nal_reserve > 0)
|
||||
nal_reserve = 0;
|
||||
len = sendto(handle_data_protocol_fd, (char*)photo_buf, sendlen+sizeof(data_head), MSG_DONTWAIT, (struct sockaddr *)&addrServer, sizeof(struct sockaddr));
|
||||
pktcnt++;
|
||||
}
|
||||
net_h264_sema_up();
|
||||
ie = disable_irq();
|
||||
status_unlock = 1;
|
||||
enable_irq(ie);
|
||||
ret = net_h264_status_sema_down(200);
|
||||
|
||||
BABY_DBG("status:%d lostnum:%d\r\n",client_frame.status,client_frame.lost_num);
|
||||
|
||||
framelen = h264_fb->len;
|
||||
pktcnt = 0;
|
||||
datoffset = 0;
|
||||
lostidx = 0;
|
||||
lostloop = 3; //所有丢包都重传3次,增加接收成功率
|
||||
|
||||
if(client_frame.lost_num != 0){
|
||||
nal_reserve = 0;
|
||||
if(h264_fb->stype == FSTYPE_H264_FILE) {
|
||||
if(h264->type == 1) {
|
||||
nal_reserve = h264->pps_len + h264->sps_len + 12;
|
||||
}
|
||||
else if(h264->type == 1) {
|
||||
nal_reserve = 4;
|
||||
}
|
||||
}
|
||||
if(nal_reserve > 0) {
|
||||
if(h264->type == 1) {
|
||||
*((uint32_t*)(photo_buf+sizeof(data_head))) = 0x1000000;
|
||||
os_memcpy(photo_buf+sizeof(data_head)+4, h264->sps, h264->sps_len);
|
||||
*((uint32_t*)(photo_buf+sizeof(data_head)+h264->sps_len+4)) = 0x1000000;
|
||||
os_memcpy(photo_buf+sizeof(data_head)+h264->sps_len+8, h264->pps, h264->pps_len);
|
||||
*((uint32_t*)(photo_buf+sizeof(data_head)+h264->pps_len+h264->sps_len+8)) = 0x1000000;
|
||||
}
|
||||
else {
|
||||
*((uint32_t*)(photo_buf+sizeof(data_head))) = 0x1000000;
|
||||
}
|
||||
}
|
||||
while(framelen != 0){
|
||||
data_head_msg->pack = pktcnt;
|
||||
if(framelen >= (MAX_VIDEO_PKT_LEN - nal_reserve)){
|
||||
framelen = framelen - (MAX_VIDEO_PKT_LEN-nal_reserve);
|
||||
memcpy(photo_buf+sizeof(data_head)+nal_reserve,h264_fb->data+datoffset,(MAX_VIDEO_PKT_LEN-nal_reserve));
|
||||
datoffset += (MAX_VIDEO_PKT_LEN-nal_reserve);
|
||||
sendlen = MAX_VIDEO_PKT_LEN;
|
||||
}else{
|
||||
memcpy(photo_buf+sizeof(data_head)+nal_reserve,h264_fb->data+datoffset,framelen);
|
||||
sendlen = framelen + nal_reserve;
|
||||
framelen = 0;
|
||||
}
|
||||
if(pktcnt == client_frame.lost_packet[lostidx]){
|
||||
lostidx++;
|
||||
for(itk = 0;itk < lostloop;itk++){
|
||||
len = sendto(handle_data_protocol_fd, (char*)photo_buf, sendlen+sizeof(data_head), MSG_DONTWAIT, (struct sockaddr *)&addrServer, sizeof(struct sockaddr));
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
if(nal_reserve > 0)
|
||||
nal_reserve = 0;
|
||||
pktcnt++;
|
||||
}
|
||||
client_frame.status = 0;
|
||||
net_h264_sema_up();
|
||||
|
||||
ie = disable_irq();
|
||||
status_unlock = 1;
|
||||
enable_irq(ie);
|
||||
ret = net_h264_status_sema_down(200);
|
||||
|
||||
BABY_DBG("status:%d down:%d\r\n",client_frame.status,ret);
|
||||
if(client_frame.status == 3){
|
||||
h264_reflash_new_gop(1,1);
|
||||
BABY_DBG("frame maybe lost,produce I frame.......\r\n");
|
||||
framesuc = 0;
|
||||
}
|
||||
}
|
||||
recfg_babymonitor_msg(framesuc);
|
||||
delete_frame:
|
||||
//_os_printf("U(%d %d)",h264->count,lostframe);
|
||||
oldcount = h264->count;
|
||||
msi_delete_fb(NULL, h264_fb);
|
||||
}else{
|
||||
os_sleep_ms(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void udp_handle_client_init()
|
||||
{
|
||||
csi_kernel_task_new((k_task_entry_t)udp_handle_client_status_thread, "handle_udp_pkt", 0, 25, 0, NULL, 1024, &handle_task_recv);
|
||||
csi_kernel_task_new((k_task_entry_t)udp_handle_client_data_thread, "handle_data_udp_pkt", 0, 25, 0, NULL, 1024, &handle_data_task_recv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void user_tcp_write_workqueue(void *e, void *d){
|
||||
int ret;
|
||||
connect_cfg_head tcp_hand;
|
||||
if(client_dev_magic == 0)
|
||||
tcp_hand.type = 0;
|
||||
else
|
||||
tcp_hand.type = 1;
|
||||
|
||||
if(src_filter_type == FSTYPE_H264_FILE) {
|
||||
tcp_hand.w = 1280;
|
||||
tcp_hand.h = 720;
|
||||
}
|
||||
else {
|
||||
tcp_hand.w = w_gol;
|
||||
tcp_hand.h = h_gol;
|
||||
}
|
||||
tcp_hand.packet_len = MAX_VIDEO_PKT_LEN;
|
||||
tcp_hand.ip_grp = 25;
|
||||
tcp_hand.frame_rate = 20;
|
||||
tcp_hand.dev_magic = client_dev_magic;
|
||||
ret = send(tcp_connect_fd,&tcp_hand,sizeof(tcp_hand),0);
|
||||
BABY_DBG("send tcp heartbeat:%d\r\n",ret);
|
||||
}
|
||||
|
||||
void user_tcpClientread(void *e, void *d)
|
||||
{
|
||||
struct h264_device *h264_dev;
|
||||
static struct msi *h264_msi;
|
||||
static uint16_t w;
|
||||
static uint16_t h;
|
||||
int ret;
|
||||
struct vpp_device *vpp_dev;
|
||||
uint8_t tcpbuf[64];
|
||||
connect_cfg_head tcp_hand;
|
||||
h264_dev = (struct h264_device *)dev_get(HG_H264_DEVID);
|
||||
vpp_dev = (struct vpp_device *)dev_get(HG_VPP_DEVID);
|
||||
ret = read(tcp_connect_fd,tcpbuf,64);
|
||||
if(ret > 0) {
|
||||
//memcpy(&tcp_hand,tcpbuf,sizeof(tcp_hand));
|
||||
memcpy(&tcp_hand,tcpbuf,sizeof(tcp_hand));
|
||||
BABY_DBG("get len:%d tcpbuf:%02x w:%d h:%d............\r\n",ret,tcp_hand.type,tcp_hand.w,tcp_hand.h);
|
||||
if(tcp_hand.type == 0){
|
||||
heartbeat++;
|
||||
}else if(tcp_hand.type == 3){
|
||||
h264_reflash_new_gop(1,1);
|
||||
vpp_open(vpp_dev);
|
||||
}else if(tcp_hand.type == 4){
|
||||
vpp_close(vpp_dev);
|
||||
}else if(tcp_hand.type == 5){
|
||||
client_dev_magic = tcp_hand.dev_magic;
|
||||
}else{
|
||||
BABY_DBG("start tran photo\r\n");
|
||||
if(tcp_hand.type == 2){
|
||||
if(client_dev_magic == 0) { //第一次连接
|
||||
client_dev_magic = tcp_hand.dev_magic;
|
||||
h264_msi = msi_find(AUTO_H264, 1);
|
||||
if(h264_msi) {
|
||||
msi_put(h264_msi);
|
||||
msi_add_output(h264_msi, NULL, "NET_H264");
|
||||
}
|
||||
}
|
||||
w = tcp_hand.w;
|
||||
h = tcp_hand.h;
|
||||
w_gol = w;
|
||||
h_gol = h;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// _os_printf("%s %d\r\n",__func__,__LINE__);
|
||||
eloop_remove_event( tcp_read_ev );
|
||||
tcp_read_ev = NULL;
|
||||
}
|
||||
//net_tcp_sema_up();
|
||||
}
|
||||
|
||||
void tcp_handle_client_thread(){ //摄像头端
|
||||
// connect_cfg_head tcp_hand;
|
||||
int32 isstaconnect;
|
||||
int32 ret;
|
||||
struct sockaddr_in addr;
|
||||
os_memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(6001);
|
||||
addr.sin_addr.s_addr = inet_addr("192.168.169.1");
|
||||
os_sleep_ms(1000);
|
||||
reconnect:
|
||||
heartbeat = 0;
|
||||
ret = connect(tcp_connect_fd, (const struct sockaddr *)&addr, sizeof(struct sockaddr));
|
||||
if(ret < 0){
|
||||
closesocket(tcp_connect_fd);
|
||||
tcp_connect_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
printf("connect error(%d)..\r\n",tcp_connect_fd);
|
||||
os_sleep_ms(500);
|
||||
goto reconnect;
|
||||
}else{
|
||||
printf("connect finish\r\n");
|
||||
}
|
||||
|
||||
|
||||
client_addr = addr.sin_addr.s_addr;
|
||||
tcp_read_ev = eloop_add_fd( tcp_connect_fd, EVENT_READ, EVENT_F_ENABLED, user_tcpClientread, 0 );
|
||||
|
||||
#if 1
|
||||
while(1){
|
||||
ip_addr_t ipaddr;
|
||||
ipaddr = lwip_netif_get_ip2("w0");
|
||||
isstaconnect = ieee80211_conf_get_stacnt(WIFI_MODE_STA);
|
||||
|
||||
BABY_DBG("ipaddr:%x sta:%d\r\n",ipaddr.addr,ieee80211_conf_get_stacnt(WIFI_MODE_STA));
|
||||
|
||||
if(isstaconnect == 0){ //我们为sta,发现连接数为0,则表示当前连接断开,tcp事件关闭并等待重连
|
||||
_os_printf("sta lost connect,reconnect TCP \r\n");
|
||||
eloop_remove_event( tcp_read_ev );
|
||||
tcp_read_ev = NULL;
|
||||
}
|
||||
|
||||
if(tcp_read_ev == NULL){
|
||||
closesocket( tcp_connect_fd );
|
||||
tcp_connect_fd = -1;
|
||||
tcp_connect_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
os_sleep_ms(500);
|
||||
goto reconnect;
|
||||
}else{
|
||||
eloop_add_alarm(os_jiffies(),EVENT_F_ENABLED,user_tcp_write_workqueue,0);
|
||||
}
|
||||
|
||||
os_sleep_ms(1000);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void tcp_handle_client_thread_init(){
|
||||
tcp_connect_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
csi_kernel_task_new((k_task_entry_t)tcp_handle_client_thread, "handle_connect_tcp_pkt", NULL, 25, 0, NULL, 1024, &handle_tcp_task_recv);
|
||||
}
|
||||
|
||||
void tcp_handle_client_init(){
|
||||
tcp_handle_client_thread_init();
|
||||
}
|
||||
|
||||
void client_frame_msg_init(uint8_t frame_num,uint8_t timeout){
|
||||
client_frame.framenum = frame_num;
|
||||
client_frame.time = 0;
|
||||
client_frame.status = 0;
|
||||
client_frame.lost_num = 0;
|
||||
client_frame.timeout = timeout;
|
||||
memset(client_frame.lost_packet,0xff,100);
|
||||
}
|
||||
|
||||
void protocol_client_init(){
|
||||
os_mutex_init(&thread_lock);
|
||||
net_h264_sema_init();
|
||||
net_h264_status_sema_init();
|
||||
client_frame_msg_init(0,10);
|
||||
udp_handle_client_init();
|
||||
//net_tcp_sema_init();
|
||||
tcp_handle_client_init();
|
||||
}
|
||||
|
||||
void protocol_client_send_enable(uint8_t enable)
|
||||
{
|
||||
struct msi *h264_msi = NULL;
|
||||
h264_msi = msi_find(AUTO_H264, 1);
|
||||
if(h264_msi) {
|
||||
msi_put(h264_msi);
|
||||
if(enable)
|
||||
msi_add_output(h264_msi, NULL, "NET_H264");
|
||||
else
|
||||
msi_del_output(h264_msi, NULL, "NET_H264");
|
||||
}
|
||||
}
|
||||
|
||||
void protocol_client_filtertype(uint8_t type)
|
||||
{
|
||||
src_filter_type = type;
|
||||
}
|
||||
|
||||
void user_protocol()
|
||||
{
|
||||
protocol_client_filtertype(FSTYPE_H264_GEN420_DATA);
|
||||
protocol_client_init(); //发送摄像头数据 STA
|
||||
}
|
||||
|
||||
#endif
|
||||
116
sdk/app/babyprotocol/babyprotocol_h264.h
Normal file
116
sdk/app/babyprotocol/babyprotocol_h264.h
Normal file
@@ -0,0 +1,116 @@
|
||||
#ifndef _PHOTO_TRAN_PROTOCOL_
|
||||
#define _PHOTO_TRAN_PROTOCOL_
|
||||
|
||||
#include "osal/string.h"
|
||||
#include "lib/net/eloop/eloop.h"
|
||||
|
||||
//#define OPEN_DBG 1
|
||||
#if OPEN_DBG
|
||||
#define BABY_DBG(fmt, ...) _os_printf(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define BABY_DBG(fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t type; //0:连接请求 1:开始图传 2:cfg
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
uint32_t packet_len; //分包长度
|
||||
uint32_t ip_grp; //IP比例,如25,则表示1个I帧,24个P帧
|
||||
uint32_t frame_rate; //帧率
|
||||
uint32_t dev_magic; //设备特征码
|
||||
}connect_cfg_head;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t framenum; //0~255,每帧+1
|
||||
uint8_t cnt; //当前包需要分多少数据包
|
||||
uint8_t pack; //当前包num
|
||||
uint8_t frmtype; //当前是I帧还是P帧
|
||||
}data_head;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t framenum; //当前帧num
|
||||
uint8_t type; //0:当前帧接收完整 1:请求屏/app发送状态msg 2:当前帧数据缺失
|
||||
}status_msg;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t time; //发送完成的时间
|
||||
uint32_t dev_magic; //设备特征码
|
||||
uint8_t framenum; //当前帧num
|
||||
uint8_t status; //0:wait client status 1:sending status to client 2:get client status 3:frame lost
|
||||
uint8_t timeout; //超时多久后发送状态请求
|
||||
uint8_t lost_num; //当前获取状态后,丢包情况
|
||||
uint8_t lost_packet[100]; //如果有丢包,分别是哪些包
|
||||
|
||||
}frame_msg;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *addr;
|
||||
uint32_t len;
|
||||
uint32_t timeinf;
|
||||
uint16_t num;
|
||||
uint16_t type;
|
||||
uint16_t devid;
|
||||
uint16_t framerate;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
}decode_msg;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ipaddr;
|
||||
uint32_t tcpfd;
|
||||
uint32_t udp_status_fd;
|
||||
uint32_t udp_data_fd;
|
||||
uint32_t udp_status_task;
|
||||
EVT_HDL udp_read_status_ev;
|
||||
uint32_t udp_data_task;
|
||||
uint32_t dev_id;
|
||||
uint32_t frame_rate;
|
||||
uint8_t *psram_photo;
|
||||
uint8_t larger;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
}dev_map;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t speed;
|
||||
uint8_t frame_tx_lost;
|
||||
uint8_t frame_tx_success;
|
||||
uint8_t frame_rx_lost;
|
||||
uint8_t frame_rx_success;
|
||||
}babymonitor_msg;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t target_width;
|
||||
uint32_t target_high;
|
||||
}target_resolution;
|
||||
|
||||
|
||||
#define MAIN_SENSOR_STILL_MIN 300
|
||||
#define MAIN_SENSOR_STILL_MAX 600
|
||||
#define MAIN_SENSOR_MOVE_MIN 800
|
||||
#define MAIN_SENSOR_MOVE_MAX 1500
|
||||
|
||||
#define SEC_SENSOR_STILL_MIN 200
|
||||
#define SEC_SENSOR_STILL_MAX 400
|
||||
#define SEC_SENSOR_MOVE_MIN 400
|
||||
#define SEC_SENSOR_MOVE_MAX 1000
|
||||
|
||||
|
||||
#define BPS_STEP 50
|
||||
#define UP_BPS_FRM_NUM 25
|
||||
|
||||
#ifdef SYS_APP_BBM_LCD
|
||||
extern void protocol_server_change_resolution(uint8_t id,uint32_t width, uint32_t high);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
104
sdk/app/babyprotocol/babyprotocol_playback.c
Normal file
104
sdk/app/babyprotocol/babyprotocol_playback.c
Normal file
@@ -0,0 +1,104 @@
|
||||
#include "basic_include.h"
|
||||
#include "stream_define.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "video_app_h264_msi.h"
|
||||
#include "audio_msi/audio_adc.h"
|
||||
#include "audio_media_ctrl/audio_code_ctrl.h"
|
||||
#include "intercom/intercom.h"
|
||||
#include "babyprotocol_playback.h"
|
||||
#include "babyprotocol_h264.h"
|
||||
|
||||
#ifdef SYS_APP_BBM_CAM
|
||||
|
||||
extern struct msi *mp4_demux_msi_init(const char *msi_name, const char *filename);
|
||||
extern void protocol_client_filtertype(uint8_t type);
|
||||
|
||||
static struct msi *playback_msi = NULL;
|
||||
static struct msi *aac_msi = NULL;
|
||||
|
||||
int32_t client_remote_playback_init(const char *filename)
|
||||
{
|
||||
struct msi *opus_msi = NULL;
|
||||
AUDEC_INIT audec_init;
|
||||
if(playback_msi) {
|
||||
msi_destroy(playback_msi);
|
||||
audio_decode_deinit(aac_msi);
|
||||
}
|
||||
audec_init.track_type = MEDIA_TRACK;
|
||||
audec_init.priority = play_interruptible;
|
||||
audec_init.direct_to_dac = 0;
|
||||
audec_init.destroy_self = 0;
|
||||
audec_init.use_tpc = 0;
|
||||
audec_init.src_msi = NULL;
|
||||
aac_msi = audio_decode_init(AAC_DEC, 8000, &audec_init);
|
||||
if(aac_msi == NULL) {
|
||||
return RET_ERR;
|
||||
}
|
||||
protocol_client_filtertype(FSTYPE_H264_FILE);
|
||||
intercom_encode_pause(1, 1);
|
||||
opus_msi = msi_find("SR_OPUS_ENCODE", 1);
|
||||
if(opus_msi) {
|
||||
msi_put(opus_msi);
|
||||
audio_code_set_src_msi(opus_msi, aac_msi);
|
||||
}
|
||||
intercom_encode_pause(0, 0);
|
||||
os_sleep_ms(100);
|
||||
playback_msi = mp4_demux_msi_init("bbm_playback_mp4", filename);
|
||||
if(playback_msi) {
|
||||
msi_add_output(playback_msi, NULL, "NET_H264");
|
||||
audio_code_set_src_msi(aac_msi, playback_msi);
|
||||
intercom_set_stream_type(intercom_live_audio, intercom_playback_audio);
|
||||
msi_do_cmd(playback_msi, MSI_CMD_VIDEO_DEMUX_CTRL, MSI_VIDEO_DEMUX_START, 0);
|
||||
return RET_OK;
|
||||
}
|
||||
audio_decode_deinit(aac_msi);
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
int32_t client_remote_playback_deinit(void)
|
||||
{
|
||||
struct msi *opus_msi = NULL;
|
||||
if(playback_msi) {
|
||||
msi_destroy(playback_msi);
|
||||
os_sleep_ms(100);
|
||||
protocol_client_filtertype(FSTYPE_H264_GEN420_DATA);
|
||||
audio_decode_deinit(aac_msi);
|
||||
intercom_encode_pause(1, 1);
|
||||
opus_msi = msi_find("SR_OPUS_ENCODE", 1);
|
||||
if(opus_msi) {
|
||||
msi_put(opus_msi);
|
||||
audio_code_set_src_msi(opus_msi, get_auadc_msi(AUSYS_AUAD));
|
||||
}
|
||||
intercom_set_stream_type(intercom_live_audio, intercom_live_audio);
|
||||
intercom_encode_pause(0, 0);
|
||||
}
|
||||
playback_msi = NULL;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static uint32_t playback = 0;
|
||||
static uint8_t playback_file_name[50] = {0};
|
||||
static void mp4_playback_thread(void *d)
|
||||
{
|
||||
if(playback == 1) {
|
||||
os_printf("\n***playback:%s***\n",playback_file_name);
|
||||
client_remote_playback_init((const char*)playback_file_name);
|
||||
}
|
||||
else if(playback == 0) {
|
||||
client_remote_playback_deinit();
|
||||
}
|
||||
}
|
||||
|
||||
int32 atcmd_bbm_client_playback(const char *cmd, char *argv[], uint32 argc)
|
||||
{
|
||||
if(argc >= 2) {
|
||||
playback = os_atoi(argv[1]);
|
||||
os_memset(playback_file_name, 0, 50);
|
||||
os_memcpy(playback_file_name,argv[0],strlen(argv[0]));
|
||||
os_task_create("mp4_playback_thread", mp4_playback_thread, NULL, OS_TASK_PRIORITY_NORMAL, 0, NULL, 2048);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
7
sdk/app/babyprotocol/babyprotocol_playback.h
Normal file
7
sdk/app/babyprotocol/babyprotocol_playback.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef _BABYPROCOL_PLAYBACK_H_
|
||||
#define _BABYPROCOL_PLAYBACK_H_
|
||||
|
||||
extern int32_t client_remote_playback_init(const char *filename);
|
||||
extern int32_t client_remote_playback_deinit(void);
|
||||
|
||||
#endif
|
||||
108
sdk/app/babyprotocol/babyprotocol_record.c
Normal file
108
sdk/app/babyprotocol/babyprotocol_record.c
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "basic_include.h"
|
||||
#include "stream_define.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "video_app_h264_msi.h"
|
||||
#include "audio_media_ctrl/audio_code_ctrl.h"
|
||||
#include "audio_msi/audio_adc.h"
|
||||
#include "intercom/intercom.h"
|
||||
#include "babyprotocol_record.h"
|
||||
#include "app/video_app/file_thumb.h"
|
||||
#include "recorder/file_process.h"
|
||||
#include "fs/fatfs/osal_file.h"
|
||||
#include "app/loop_record_moudle/loop_record_moudle.h"
|
||||
#include "app/video_app/file_common_api.h"
|
||||
|
||||
#ifdef SYS_APP_BBM_CAM
|
||||
|
||||
struct msi *mp4_encode_msi2_init(const char *mp4_msi_name, uint8_t srcID, uint8_t filter_type, uint8_t rec_time,
|
||||
uint32_t audio_encode, struct file_process *file_process, uint8_t mode);
|
||||
|
||||
static struct msi *rec_msi = NULL;
|
||||
static struct msi *h264_msi = NULL;
|
||||
static struct msi *aac_msi = NULL;
|
||||
|
||||
int32_t client_local_record_init(uint32_t record_time_minutes)
|
||||
{
|
||||
AUENC_INIT auenc_init;
|
||||
if(!rec_msi) {
|
||||
h264_msi = msi_find(AUTO_H264, 1);
|
||||
if(h264_msi) {
|
||||
msi_put(h264_msi);
|
||||
auenc_init.destroy_self = 0;
|
||||
auenc_init.src_msi = get_auadc_msi(AUSYS_AUAD);
|
||||
aac_msi = audio_encode_init(AAC_ENC, audio_adc_get_samplerate(AUSYS_AUAD), &auenc_init);
|
||||
if(!aac_msi) {
|
||||
h264_msi = NULL;
|
||||
return RET_ERR;
|
||||
}
|
||||
struct file_process mp4_file_process = {
|
||||
.loop = NULL,
|
||||
.rec_path = REC_PATH,
|
||||
.ext_name = MP4_EXTENSION_NAME,
|
||||
.create_file = rec_create_file,
|
||||
.loop_free = rec_loop_free,
|
||||
.lock_file = NULL,
|
||||
};
|
||||
rec_msi = mp4_encode_msi2_init("bbm_record_mp4", FRAMEBUFF_SOURCE_CAMERA0, FSTYPE_H264_VPP_DATA0,
|
||||
record_time_minutes, AAC_ENC, &mp4_file_process, 0);
|
||||
if(rec_msi) {
|
||||
msi_add_output(h264_msi, NULL, "bbm_record_mp4");
|
||||
audio_code_add_output(aac_msi, "bbm_record_mp4");
|
||||
msi_do_cmd(rec_msi, MSI_CMD_MEDIA_CTRL, MSI_MEDIA_CTRL_RECORD_START, 0);
|
||||
return RET_OK;
|
||||
}
|
||||
else {
|
||||
h264_msi = NULL;
|
||||
audio_encode_deinit(aac_msi);
|
||||
aac_msi = NULL;
|
||||
return RET_ERR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return RET_ERR;
|
||||
}
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32_t client_local_record_deinit(void)
|
||||
{
|
||||
if(rec_msi) {
|
||||
if(h264_msi) {
|
||||
msi_del_output(h264_msi, NULL, "bbm_record_mp4");
|
||||
}
|
||||
if(aac_msi) {
|
||||
audio_code_del_output(aac_msi, "bbm_record_mp4");
|
||||
audio_encode_deinit(aac_msi);
|
||||
}
|
||||
msi_destroy(rec_msi);
|
||||
rec_msi = NULL;
|
||||
h264_msi = NULL;
|
||||
aac_msi = NULL;
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static uint32_t mp4_record = 0;
|
||||
static void mp4_record_thread(void *d)
|
||||
{
|
||||
uint32_t state = *((uint32_t*)d);
|
||||
if(state == 1) {
|
||||
client_local_record_init(1);
|
||||
}
|
||||
else if(state == 0) {
|
||||
client_local_record_deinit();
|
||||
}
|
||||
}
|
||||
|
||||
int32 atcmd_bbm_client_record(const char *cmd, char *argv[], uint32 argc)
|
||||
{
|
||||
if(argc >= 1) {
|
||||
mp4_record = os_atoi(argv[0]);
|
||||
os_task_create("mp4_record_thread", mp4_record_thread, &mp4_record, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
7
sdk/app/babyprotocol/babyprotocol_record.h
Normal file
7
sdk/app/babyprotocol/babyprotocol_record.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef _BABYPROTOCOL_RECORD_H_
|
||||
#define _BABYPROTOCOL_RECORD_H_
|
||||
|
||||
extern int32_t client_local_record_init(uint32_t record_time_minutes);
|
||||
extern int32_t client_local_record_deinit(void);
|
||||
|
||||
#endif
|
||||
975
sdk/app/babyprotocol/babyprotocol_server_h264.c
Normal file
975
sdk/app/babyprotocol/babyprotocol_server_h264.c
Normal file
@@ -0,0 +1,975 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "netif/ethernetif.h"
|
||||
#include "stream_define.h"
|
||||
#include "stream_frame.h"
|
||||
#include "babyprotocol_h264.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "scale_msi/scale_msi.h"
|
||||
#include "lib/video/h264/h264_drv.h"
|
||||
|
||||
#ifdef SYS_APP_BBM_LCD
|
||||
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define MAX_VIDEO_PKT_LEN 1430
|
||||
|
||||
static int8_t next_switch_device = 2;
|
||||
static int8_t cur_switch_device = 2;
|
||||
|
||||
//static struct os_semaphore net_h264_sem = {0,NULL};
|
||||
struct os_msgqueue net_h264_msg;
|
||||
|
||||
static int handle_protocol_fd = - 1;
|
||||
static int handle_data_protocol_fd = - 1;
|
||||
|
||||
int handle_protocol_table_fd[10];
|
||||
int handle_data_protocol_table_fd[10];
|
||||
|
||||
static int tcp_connect_fd = -1;
|
||||
|
||||
|
||||
|
||||
//static k_task_handle_t handle_tcp_task_recv;
|
||||
//static in_addr_t client_addr = 0;
|
||||
|
||||
|
||||
|
||||
volatile uint32 server_frame_rate;
|
||||
|
||||
#define STA_NUM 2
|
||||
#define DEC_TABLE_NUM 32
|
||||
decode_msg decmsg[DEC_TABLE_NUM];
|
||||
|
||||
|
||||
uint32_t devnum = 0;
|
||||
dev_map devtab[11];
|
||||
frame_msg server_frame[10];
|
||||
|
||||
static volatile target_resolution server_resolution[STA_NUM];
|
||||
|
||||
uint8_t photo_buf[1440] __attribute__ ((aligned(4)));;
|
||||
uint8 psram_h264_photo[200*1024] __attribute__ ((aligned(4),section(".psram.src")));
|
||||
int frame_for_dec = 0;
|
||||
uint8_t dispnum;
|
||||
uint16_t rx_speed,tx_speed;
|
||||
EVT_HDL udp_read_status_ev;
|
||||
extern struct msi *scale2_msi(const char *name, uint16_t iw, uint16_t ih, uint16_t ow, uint16_t oh, uint16_t type,uint8_t larger);
|
||||
extern void get_h264_stream_w_h(uint16_t* w,uint16_t* h,uint8_t *h264data);
|
||||
void net_h264_sema_init()
|
||||
{
|
||||
os_msgq_init(&net_h264_msg,4);
|
||||
}
|
||||
|
||||
uint32 net_h264_sema_down(int32 tmo_ms)
|
||||
{
|
||||
uint32 retval;
|
||||
uint32 retdata;
|
||||
//os_sema_down(&net_h264_sem,tmo_ms);
|
||||
retdata = os_msgq_get2(&net_h264_msg, tmo_ms, (int32_t*)(&retval));
|
||||
if(retval == 0){
|
||||
return retdata;
|
||||
}else{
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
void net_h264_sema_up(uint32 clientaddr)
|
||||
{
|
||||
int32 ret;
|
||||
ret = os_msgq_put(&net_h264_msg, clientaddr, osWaitForever);
|
||||
if(ret != 0){
|
||||
_os_printf("wakeup msg err:%d\r\n",ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int usr_protocol_create_server(uint16_t port)
|
||||
{
|
||||
int socket_c, err;
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_len = sizeof(struct sockaddr_in);
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = htons(INADDR_ANY);
|
||||
|
||||
socket_c = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket_c < 0)
|
||||
{
|
||||
printf("get socket err");
|
||||
return - 1;
|
||||
}
|
||||
|
||||
err = bind(socket_c, (struct sockaddr*) &addr, sizeof(struct sockaddr_in));
|
||||
|
||||
if (err == - 1)
|
||||
{
|
||||
close(socket_c);
|
||||
return - 1;
|
||||
|
||||
}
|
||||
return socket_c;
|
||||
}
|
||||
|
||||
int usr_protocol_create_server_with_ip(uint16_t port,uint32_t ipaddr)
|
||||
{
|
||||
int socket_c, err;
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_len = sizeof(struct sockaddr_in);
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = htons(INADDR_ANY);//ipaddr;//
|
||||
//_os_printf("IP:%x %x %x\r\n",ipaddr,htons(INADDR_ANY),inet_addr("192.168.169.100"));
|
||||
socket_c = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket_c < 0)
|
||||
{
|
||||
printf("get socket err");
|
||||
return - 1;
|
||||
}
|
||||
|
||||
err = bind(socket_c, (struct sockaddr*) &addr, sizeof(struct sockaddr_in));
|
||||
|
||||
if (err == - 1)
|
||||
{
|
||||
close(socket_c);
|
||||
return - 1;
|
||||
|
||||
}
|
||||
return socket_c;
|
||||
}
|
||||
|
||||
|
||||
void udp_handle_server_status_write_workqueue(void *ei, void *d){
|
||||
int tos;
|
||||
struct sockaddr_in *addrServer;
|
||||
status_msg *msg_head;
|
||||
char buf[12];
|
||||
int len;
|
||||
uint8_t itk;
|
||||
uint8_t id = 0;
|
||||
uint8_t fd;
|
||||
addrServer = d;
|
||||
for(itk = 0;itk < 10;itk++){
|
||||
if(addrServer->sin_addr.s_addr == devtab[itk].ipaddr){
|
||||
id = devtab[itk].dev_id;
|
||||
fd = devtab[itk].udp_status_fd;
|
||||
}
|
||||
}
|
||||
|
||||
msg_head = (status_msg *)buf;
|
||||
msg_head->framenum = server_frame[id-1].framenum;
|
||||
msg_head->type = 0;
|
||||
//len = sendto(fd, (char*)buf, 2, MSG_DONTWAIT, (struct sockaddr *)d, sizeof(struct sockaddr));
|
||||
tos = IPTOS_PREC_NETCONTROL; // 最高优先级
|
||||
setsockopt(handle_protocol_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
|
||||
len = sendto(handle_protocol_fd, (char*)buf, 2, MSG_DONTWAIT, (struct sockaddr *)d, sizeof(struct sockaddr));
|
||||
tos = IPTOS_PREC_ROUTINE; // 最低优先级
|
||||
setsockopt(handle_protocol_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
|
||||
|
||||
}
|
||||
|
||||
void udp_handle_server_status_read_workqueue(void *ei, void *status_fd){
|
||||
int tos;
|
||||
int retval;
|
||||
int ret;
|
||||
uint8_t itk;
|
||||
uint8_t handlebuf[96];
|
||||
struct sockaddr remote_addr;
|
||||
struct sockaddr_in *addrServer;
|
||||
status_msg *msg_head;
|
||||
uint8_t id = 0;
|
||||
msg_head = (status_msg *)handlebuf;
|
||||
retval = 16;
|
||||
int32_t fd = (int32_t)status_fd;
|
||||
ret = recvfrom (fd, handlebuf, 24, 0, &remote_addr, (socklen_t*)&retval);
|
||||
// _os_printf(" G");
|
||||
addrServer = (struct sockaddr_in *)(&remote_addr);
|
||||
for(itk = 0;itk < 10;itk++){
|
||||
if(addrServer->sin_addr.s_addr == devtab[itk].ipaddr){
|
||||
id = devtab[itk].dev_id;
|
||||
}
|
||||
}
|
||||
|
||||
if((id == 0)||(id > 3)) //当前设备号不存在,先只支持三台设备
|
||||
{
|
||||
BABY_DBG(" status no this client dev....");
|
||||
return;
|
||||
}
|
||||
|
||||
id = id-1; //设备号是从1开始计算,这里让设备号改成从0开始算
|
||||
//os_printf("client read:%02d type:%d lost_num:%d \r\n",msg_head->framenum,msg_head->type,server_frame[id-1].lost_num);
|
||||
if(server_frame[id].lost_num != 0){
|
||||
BABY_DBG("L(%d %d)",id,server_frame[id].lost_num);
|
||||
}else{
|
||||
BABY_DBG("R%d",id);
|
||||
}
|
||||
|
||||
if(server_frame[id].framenum != msg_head->framenum){
|
||||
BABY_DBG("ag%d",id);
|
||||
return;
|
||||
}
|
||||
|
||||
if(server_frame[id].lost_num != 0){
|
||||
msg_head = (status_msg *)handlebuf;
|
||||
msg_head->framenum = server_frame[id].framenum;
|
||||
msg_head->type = 2;
|
||||
for(itk = 0;itk < server_frame[id].lost_num;itk++){
|
||||
handlebuf[2+itk] = server_frame[id].lost_packet[itk];
|
||||
}
|
||||
}else{
|
||||
msg_head->framenum = server_frame[id].framenum;
|
||||
msg_head->type = 0;
|
||||
}
|
||||
BABY_DBG("S(%d %d)",id,msg_head->type);
|
||||
tos = IPTOS_PREC_NETCONTROL; // 最高优先级
|
||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
|
||||
sendto(fd, handlebuf, 2+server_frame[id].lost_num, MSG_DONTWAIT, &remote_addr, sizeof(struct sockaddr));
|
||||
tos = IPTOS_PREC_ROUTINE; // 最低优先级
|
||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
|
||||
}
|
||||
|
||||
|
||||
void udp_handle_server_status_thread(void *d){
|
||||
struct sockaddr_in addrServer;
|
||||
in_addr_t cli_addr;
|
||||
dev_map *dev_tbl;
|
||||
dev_tbl = d;
|
||||
memset(&addrServer,0,sizeof(struct sockaddr_in));
|
||||
|
||||
addrServer.sin_family=AF_INET;
|
||||
addrServer.sin_addr.s_addr= inet_addr("255.255.255.255");//client_addr;//inet_addr("192.168.169.1");
|
||||
addrServer.sin_port=htons(6003);
|
||||
//dev_tbl->udp_read_status_ev = eloop_add_fd( dev_tbl->udp_status_fd, EVENT_READ, EVENT_F_ENABLED, udp_handle_server_status_read_workqueue, &dev_tbl->udp_status_fd );
|
||||
dev_tbl->udp_read_status_ev = eloop_add_fd( handle_protocol_fd, EVENT_READ, EVENT_F_ENABLED, udp_handle_server_status_read_workqueue, (void*)handle_protocol_fd );
|
||||
|
||||
while(1){
|
||||
cli_addr = net_h264_sema_down(-1);
|
||||
addrServer.sin_addr.s_addr = cli_addr;
|
||||
eloop_add_alarm(os_jiffies(),EVENT_F_ENABLED,udp_handle_server_status_write_workqueue,(void *)&addrServer); //eventloop send
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t mark_lost_pkt(uint8_t pkt,uint8_t *rxbuf){
|
||||
uint8_t get_cnt[100];
|
||||
uint32_t itk;
|
||||
uint8_t pktrx = 0;
|
||||
for(itk = 0;itk < 100;itk++){
|
||||
if(rxbuf[itk] != 0xff){
|
||||
if(pkt == rxbuf[itk]){ //接收到的清空
|
||||
rxbuf[itk] = 0xff;
|
||||
}else{
|
||||
get_cnt[pktrx] = rxbuf[itk]; //多少个pkt还未接收
|
||||
pktrx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memset(rxbuf,0xff,100);
|
||||
//server_frame.lost_num = pktrx;
|
||||
for(itk = 0;itk < pktrx;itk++){
|
||||
rxbuf[itk] = get_cnt[itk];
|
||||
}
|
||||
|
||||
return pktrx;
|
||||
}
|
||||
|
||||
void udp_handle_server_data_thread(uint32_t *d){
|
||||
uint32 timer_ref = 0;
|
||||
uint32 timer_ref2 = 0;
|
||||
int retval;
|
||||
int ret;
|
||||
int len;
|
||||
int itk = 0;
|
||||
|
||||
uint16_t w = 0;
|
||||
uint16_t h = 0;
|
||||
struct sockaddr_in remote_addr;
|
||||
uint16_t rx_speed_cnt = 0;
|
||||
uint16_t dispnum_cnt = 0;
|
||||
uint8_t push_lcd_success[10];
|
||||
uint16_t framenum[10];
|
||||
uint32_t framelen[10];
|
||||
uint16_t oldframecnt[10];
|
||||
uint8_t id;
|
||||
uint32_t framerate = 0;
|
||||
uint8_t type[10];
|
||||
uint8_t cntnum[10];
|
||||
uint8_t pktnum[10];
|
||||
uint8_t *fbuf;
|
||||
uint32 ie;
|
||||
uint8_t *psarm_room = NULL;
|
||||
data_head *frame_hand;
|
||||
retval = 16;
|
||||
|
||||
//framenum = 0xffff; //初始化值
|
||||
memset(framenum,0xff,sizeof(framenum));
|
||||
memset(oldframecnt,0,sizeof(oldframecnt));
|
||||
memset(framelen,0,sizeof(framelen));
|
||||
memset(cntnum,0,sizeof(cntnum));
|
||||
memset(pktnum,0,sizeof(pktnum));
|
||||
memset(type,0,sizeof(type));
|
||||
frame_hand = (data_head *)photo_buf;
|
||||
while(1){
|
||||
//ret = recvfrom (dev_tbl->udp_data_fd, photo_buf, MAX_VIDEO_PKT_LEN+sizeof(data_head), 0, &remote_addr, (socklen_t*)&retval);
|
||||
ret = recvfrom (handle_data_protocol_fd, photo_buf, MAX_VIDEO_PKT_LEN+sizeof(data_head), 0, (struct sockaddr*)(&remote_addr), (socklen_t*)&retval);
|
||||
if(next_switch_device == -1) {
|
||||
continue;
|
||||
}
|
||||
id = 0;
|
||||
for(itk = 0;itk < 10;itk++){
|
||||
if(remote_addr.sin_addr.s_addr == devtab[itk].ipaddr){
|
||||
id = devtab[itk].dev_id;
|
||||
psarm_room = devtab[itk].psram_photo;
|
||||
framerate = devtab[itk].frame_rate;
|
||||
w = devtab[itk].w;
|
||||
h = devtab[itk].h;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if((id == 0)||(id > 3)) //当前设备号不存在,先只支持三台设备
|
||||
{
|
||||
BABY_DBG("no this client dev....");
|
||||
continue;
|
||||
}
|
||||
|
||||
id = id-1; //设备号是从1开始计算,这里让设备号改成从0开始算
|
||||
if(ret >0){
|
||||
if((os_jiffies() - timer_ref) > 2000){
|
||||
rx_speed = rx_speed_cnt;
|
||||
rx_speed_cnt = 0;
|
||||
timer_ref = os_jiffies();
|
||||
}
|
||||
rx_speed_cnt += ret;
|
||||
}
|
||||
|
||||
if(framenum[id] != frame_hand->framenum){
|
||||
if(framenum[id] != 0xffff){
|
||||
if(cntnum[id] != pktnum[id]){
|
||||
BABY_DBG("lost frame\r\n");
|
||||
}
|
||||
}
|
||||
BABY_DBG("frame:%d type:%d id:%d\r\n",frame_hand->framenum,frame_hand->frmtype,id);
|
||||
framenum[id] = frame_hand->framenum;
|
||||
type[id] = frame_hand->frmtype;
|
||||
cntnum[id] = frame_hand->cnt;
|
||||
pktnum[id] = 0;
|
||||
framelen[id] = 0;
|
||||
server_frame[id].framenum = framenum[id];
|
||||
memset(server_frame[id].lost_packet,0xff,100);
|
||||
for(itk = 0;itk < cntnum[id];itk++){
|
||||
server_frame[id].lost_packet[itk] = itk;
|
||||
}
|
||||
pktnum[id]++; //首次进来此帧图像
|
||||
server_frame[id].lost_num = mark_lost_pkt(frame_hand->pack,server_frame[id].lost_packet);
|
||||
}else{
|
||||
for(itk = 0;itk < cntnum[id];itk++){ //后面进来图像均经过这里
|
||||
if(frame_hand->pack == server_frame[id].lost_packet[itk]){ //数据没接收过
|
||||
goto markdata;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
markdata:
|
||||
pktnum[id]++;
|
||||
server_frame[id].lost_num = mark_lost_pkt(frame_hand->pack,server_frame[id].lost_packet);
|
||||
}
|
||||
// printf("@[%d:%d:%d:%d]@",frame_hand->pack,frame_hand->cnt,frame_hand->framenum,ret);
|
||||
|
||||
len = ret - sizeof(data_head);
|
||||
framelen[id] += len;
|
||||
hw_memcpy(psarm_room+frame_hand->pack*MAX_VIDEO_PKT_LEN,photo_buf+sizeof(data_head),len);
|
||||
|
||||
|
||||
if(pktnum[id] == cntnum[id]){ //数据接收完成
|
||||
psarm_room[framelen[id]] = 0x00;
|
||||
psarm_room[framelen[id]+1] = 0x00;
|
||||
psarm_room[framelen[id]+2] = 0x00;
|
||||
psarm_room[framelen[id]+3] = 0x01;
|
||||
|
||||
|
||||
|
||||
if((oldframecnt[id]+1) != framenum[id]){ //如果序号不连续
|
||||
if((framenum[id] == 0) && (oldframecnt[id] == 255)){ //序号循环了而已
|
||||
if(type[id] == 1){ //I帧,当前gop可推屏
|
||||
push_lcd_success[id] = 1;
|
||||
}
|
||||
}else{ //真实意义上的丢失了
|
||||
if(type[id] != 1){ //不是I帧
|
||||
os_printf("error ...................frame code\r\n"); //那当前ID不能再推了
|
||||
push_lcd_success[id] = 0;
|
||||
}else{ //丢帧了,但当前还是I帧,还是可以推的
|
||||
push_lcd_success[id] = 1;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(type[id] == 1){ //I帧,当前gop可推屏
|
||||
push_lcd_success[id] = 1;
|
||||
}
|
||||
}
|
||||
if(push_lcd_success[id] == 1){ //可推送gop
|
||||
// sys_dcache_clean_range(psram_h264_photo,framelen+4);
|
||||
// h264_dec_src_264(psram_h264_photo,framelen,640,368);
|
||||
for(itk = 0;itk < DEC_TABLE_NUM;itk++){
|
||||
if(decmsg[itk].addr == NULL){
|
||||
fbuf = av_psram_malloc(framelen[id]+4);
|
||||
sys_dcache_invalid_range((uint32_t*)fbuf,framelen[id]+4);
|
||||
hw_memcpy(fbuf,psarm_room,framelen[id]+4);
|
||||
ie = disable_irq();
|
||||
decmsg[itk].addr = fbuf;
|
||||
decmsg[itk].len = framelen[id];
|
||||
decmsg[itk].timeinf = os_jiffies();
|
||||
decmsg[itk].num = framenum[id];
|
||||
decmsg[itk].type = type[id];
|
||||
decmsg[itk].devid= id; //当前完成推送的摄像头ID
|
||||
decmsg[itk].framerate = framerate;
|
||||
decmsg[itk].w = w;
|
||||
decmsg[itk].h = h;
|
||||
frame_for_dec++;
|
||||
BABY_DBG("w:%d h:%d id:%d len:%d\r\n",w,h,id,framelen[id]);
|
||||
enable_irq(ie);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(itk == DEC_TABLE_NUM) {
|
||||
os_printf("No room for dec!\r\n");
|
||||
push_lcd_success[id] = 0;
|
||||
}
|
||||
if((os_jiffies() - timer_ref2) > 2000){
|
||||
dispnum = dispnum_cnt;
|
||||
dispnum_cnt = 0;
|
||||
timer_ref2 = os_jiffies();
|
||||
}
|
||||
dispnum_cnt++;
|
||||
oldframecnt[id] = framenum[id];
|
||||
net_h264_sema_up(remote_addr.sin_addr.s_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern volatile uint8_t scaler2_dev_id;
|
||||
void udp_handle_server_decode_to_lcd_thread(){
|
||||
int itk = 0;
|
||||
uint16 w,h;
|
||||
uint16 oldw[STA_NUM];
|
||||
uint16 oldh[STA_NUM];
|
||||
uint8_t *h264dat;
|
||||
uint8_t disp_num;
|
||||
uint8_t decframe[3];
|
||||
uint32_t timeinf[3];
|
||||
// uint32_t dsptime;
|
||||
// uint32_t newdspt;
|
||||
struct scale_device *scale_dev;
|
||||
uint32 ie;
|
||||
// uint16 oldframecnt = 0xffff;
|
||||
// uint8 frame_gop_lost = 1;
|
||||
uint8_t flush_video;
|
||||
uint8_t change_pixel = 0;
|
||||
uint16_t framerate[3];
|
||||
uint16_t framecnt[3];
|
||||
uint32_t lasttime[3];
|
||||
uint32_t wanttime[3];
|
||||
lasttime[0]=lasttime[1]=lasttime[2]=0;
|
||||
wanttime[0]=wanttime[1]=wanttime[2]=0;
|
||||
scale_dev = (struct scale_device *)dev_get(HG_SCALE2_DEVID);
|
||||
while(1){
|
||||
|
||||
timeinf[0]=timeinf[1]=timeinf[2]= 0xffffffff;
|
||||
decframe[0]=decframe[1]=decframe[2]= 255;
|
||||
os_sleep_ms(2);
|
||||
|
||||
ie = disable_irq();
|
||||
framecnt[0]=framecnt[1]=framecnt[2]=0;
|
||||
disp_num = 0;
|
||||
for(itk = 0;itk < DEC_TABLE_NUM;itk++){
|
||||
if(decmsg[itk].addr != NULL){
|
||||
if(timeinf[decmsg[itk].devid] > decmsg[itk].timeinf){
|
||||
timeinf[decmsg[itk].devid] = decmsg[itk].timeinf;
|
||||
decframe[decmsg[itk].devid] = itk;
|
||||
}
|
||||
framerate[decmsg[itk].devid] = devtab[decmsg[itk].devid].frame_rate;
|
||||
framecnt[decmsg[itk].devid]++;
|
||||
disp_num++;
|
||||
}
|
||||
}
|
||||
enable_irq(ie);
|
||||
|
||||
|
||||
if(disp_num != 0){
|
||||
for(itk = 0;itk < 3;itk++){
|
||||
if(framecnt[itk] != 0){ //当前id存在帧
|
||||
flush_video = 0;
|
||||
if((os_jiffies() - lasttime[itk]) > 100){ //本次刷图像跟上次刷的时间差了100ms,那就直接推送
|
||||
flush_video = 1;
|
||||
}else{
|
||||
if(os_jiffies() > wanttime[itk]){ //时间到了推送时间,则发送
|
||||
flush_video = 1;
|
||||
}else{ //还没到推送时间,则要检查一下帧缓存有多少,如果多的话,则要适时推送
|
||||
if(framecnt[itk] > 12){ //存够12帧的话,不要想了,发送吧
|
||||
flush_video = 1;
|
||||
}else if(framecnt[itk] > 6){ //按照帧率时间减少15ms速度进行播放,以防数据拥堵引起延时
|
||||
if( os_jiffies() > (wanttime[itk] - 15)){
|
||||
flush_video = 1;
|
||||
}
|
||||
}else{
|
||||
if(os_jiffies() >= (wanttime[itk] - 10)){ //按照帧率时间减少10ms速度进行播放,如果严格按照帧率比例来整,肯定会造成数据拥堵到需提前播的位置
|
||||
flush_video = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(flush_video){
|
||||
|
||||
lasttime[itk] = os_jiffies();
|
||||
wanttime[itk] = os_jiffies()+1000/decmsg[decframe[itk]].framerate;
|
||||
scaler2_dev_id =decmsg[decframe[itk]].devid;
|
||||
sys_dcache_clean_range((uint32_t*)(decmsg[decframe[itk]].addr),decmsg[decframe[itk]].len+4);
|
||||
if(decmsg[decframe[itk]].type == 1){
|
||||
change_pixel = 0;
|
||||
}
|
||||
|
||||
if(change_pixel == 0)
|
||||
{
|
||||
h264dat = decmsg[decframe[itk]].addr;
|
||||
|
||||
if(h264dat[4] == 0x67){ //SPS
|
||||
get_h264_stream_w_h(&w,&h,h264dat);
|
||||
if(h == 368){
|
||||
h = 360;
|
||||
}
|
||||
|
||||
scale2_recfg_input_size(w,h,decmsg[decframe[itk]].devid);
|
||||
oldw[decmsg[decframe[itk]].devid] = w;
|
||||
oldh[decmsg[decframe[itk]].devid] = h;
|
||||
}
|
||||
|
||||
if((oldw[decmsg[decframe[itk]].devid] != server_resolution[decmsg[decframe[itk]].devid].target_width) || (oldh[decmsg[decframe[itk]].devid] != server_resolution[decmsg[decframe[itk]].devid].target_high)){
|
||||
BABY_DBG("drop:%d %d\r\n",decmsg[decframe[itk]].devid,decmsg[decframe[itk]].num);
|
||||
}else{
|
||||
if(next_switch_device == 2) {
|
||||
if(cur_switch_device != next_switch_device) {
|
||||
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 1);
|
||||
msi_cmd(R_VIDEO_P1, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 1);
|
||||
cur_switch_device = next_switch_device;
|
||||
}
|
||||
if(decmsg[decframe[itk]].devid == 0) {
|
||||
scale2_output_larger_local_change(decmsg[decframe[itk]].devid, devtab[decmsg[decframe[itk]].devid].larger);
|
||||
scale2_output_size_local_change(decmsg[decframe[itk]].devid,0,0,0,320,360);
|
||||
}
|
||||
else {
|
||||
scale2_output_larger_local_change(decmsg[decframe[itk]].devid, devtab[decmsg[decframe[itk]].devid].larger);
|
||||
scale2_output_size_local_change(decmsg[decframe[itk]].devid,0,320,0,320,360);
|
||||
}
|
||||
scale2_cfg_run(H264_DEC,decmsg[decframe[itk]].devid);
|
||||
h264_dec_src_264(decmsg[decframe[itk]].addr,decmsg[decframe[itk]].len,oldw[decmsg[decframe[itk]].devid],16*((oldh[decmsg[decframe[itk]].devid]+15)/16) ,decmsg[decframe[itk]].devid);
|
||||
}
|
||||
else if(next_switch_device == 0) {
|
||||
if(decmsg[decframe[itk]].devid == 0) {
|
||||
if(cur_switch_device != next_switch_device) {
|
||||
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 1);
|
||||
msi_cmd(R_VIDEO_P1, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 0);
|
||||
cur_switch_device = next_switch_device;
|
||||
}
|
||||
scale2_output_larger_local_change(decmsg[decframe[itk]].devid, devtab[decmsg[decframe[itk]].devid].larger);
|
||||
scale2_output_size_local_change(decmsg[decframe[itk]].devid,1,0,0,640,360);
|
||||
scale2_cfg_run(H264_DEC,decmsg[decframe[itk]].devid);
|
||||
h264_dec_src_264(decmsg[decframe[itk]].addr,decmsg[decframe[itk]].len,oldw[decmsg[decframe[itk]].devid],16*((oldh[decmsg[decframe[itk]].devid]+15)/16) ,decmsg[decframe[itk]].devid);
|
||||
}
|
||||
}
|
||||
else if(next_switch_device == 1){
|
||||
if(decmsg[decframe[itk]].devid == 1) {
|
||||
if(cur_switch_device != next_switch_device) {
|
||||
msi_cmd(R_VIDEO_P0, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 0);
|
||||
msi_cmd(R_VIDEO_P1, MSI_CMD_LCD_VIDEO, MSI_VIDEO_ENABLE, 1);
|
||||
cur_switch_device = next_switch_device;
|
||||
}
|
||||
scale2_output_larger_local_change(decmsg[decframe[itk]].devid,devtab[decmsg[decframe[itk]].devid].larger);
|
||||
scale2_output_size_local_change(decmsg[decframe[itk]].devid,1,0,0,640,360);
|
||||
scale2_cfg_run(H264_DEC,decmsg[decframe[itk]].devid);
|
||||
h264_dec_src_264(decmsg[decframe[itk]].addr,decmsg[decframe[itk]].len,oldw[decmsg[decframe[itk]].devid],16*((oldh[decmsg[decframe[itk]].devid]+15)/16) ,decmsg[decframe[itk]].devid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
|
||||
change_pixel = 1;
|
||||
}
|
||||
av_psram_free(decmsg[decframe[itk]].addr);
|
||||
ie = disable_irq();
|
||||
frame_for_dec--;
|
||||
decmsg[decframe[itk]].addr = NULL;
|
||||
enable_irq(ie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void udp_photo_handle_server_thread(uint32_t ipaddr,uint8_t tab){
|
||||
k_task_handle_t handle_task_recv;
|
||||
k_task_handle_t handle_data_task_recv;
|
||||
uint16_t port = 6003;
|
||||
handle_protocol_table_fd[tab] = usr_protocol_create_server_with_ip(port,ipaddr);
|
||||
port = 6002;
|
||||
handle_data_protocol_table_fd[tab] = usr_protocol_create_server_with_ip(port,ipaddr);
|
||||
BABY_DBG("build_fd:%d %d\r\n",handle_protocol_table_fd[tab],handle_data_protocol_table_fd[tab]);
|
||||
devtab[tab].udp_status_fd = handle_protocol_table_fd[tab];
|
||||
devtab[tab].udp_data_fd = handle_data_protocol_table_fd[tab];
|
||||
|
||||
csi_kernel_task_new((k_task_entry_t)udp_handle_server_status_thread, "handle_udp_pkt", &devtab[tab], 25, 0, NULL, 1024, &handle_task_recv);
|
||||
csi_kernel_task_new((k_task_entry_t)udp_handle_server_data_thread, "handle_data_udp_pkt", &devtab[tab], 25, 0, NULL, 1024, &handle_data_task_recv);
|
||||
devtab[tab].udp_status_task = (uint32_t)handle_task_recv;
|
||||
devtab[tab].udp_data_task = (uint32_t)handle_data_task_recv;
|
||||
|
||||
BABY_DBG("devtab: status->%d data->%d status_Task:%x data_Task:%x\r\n",devtab[tab].udp_status_fd,devtab[tab].udp_data_fd,devtab[tab].udp_status_task,devtab[tab].udp_data_task);
|
||||
}
|
||||
|
||||
void udp_handle_server_init()
|
||||
{
|
||||
k_task_handle_t handle_lcd_task_recv;
|
||||
static k_task_handle_t handle_task_recv;
|
||||
static k_task_handle_t handle_data_task_recv;
|
||||
uint16_t port = 6003;
|
||||
handle_protocol_fd = usr_protocol_create_server(port);
|
||||
port = 6002;
|
||||
handle_data_protocol_fd = usr_protocol_create_server(port);
|
||||
csi_kernel_task_new((k_task_entry_t)udp_handle_server_status_thread, "handle_udp_pkt", &handle_protocol_fd, 25, 0, NULL, 1024, &handle_task_recv);
|
||||
csi_kernel_task_new((k_task_entry_t)udp_handle_server_data_thread, "handle_data_udp_pkt", &handle_data_protocol_fd, 25, 0, NULL, 1024, &handle_data_task_recv);
|
||||
BABY_DBG("status:%d data:%d\r\n",handle_protocol_fd,handle_data_protocol_fd);
|
||||
|
||||
csi_kernel_task_new((k_task_entry_t)udp_handle_server_decode_to_lcd_thread, "handle_data_decode_pkt", NULL, 25, 0, NULL, 1024, &handle_lcd_task_recv);
|
||||
}
|
||||
|
||||
static void tcp_handle_server( void *ei, void *d ){
|
||||
int ret;
|
||||
// struct msi *scaler_msi;
|
||||
int maskid = 0;
|
||||
uint8_t itk = 0;
|
||||
uint8_t jtk = 0;
|
||||
uint32_t ip = 0;
|
||||
uint8_t dev = 0;
|
||||
uint8_t tab_idx;
|
||||
// static uint8_t test_recfg = 0;
|
||||
connect_cfg_head tcp_hand;
|
||||
uint8_t tcpread[64];
|
||||
int tcp_fd = (int)d;
|
||||
ret = read(tcp_fd,tcpread,64);
|
||||
if(ret > 0){
|
||||
memcpy(&tcp_hand,tcpread,sizeof(tcp_hand));
|
||||
BABY_DBG("get len:%d type:%02x w:%d h:%d............\r\n",ret,tcp_hand.type,tcp_hand.w,tcp_hand.h);
|
||||
if(tcp_hand.type == 2){
|
||||
tcp_hand.type = 2;
|
||||
tcp_hand.w = tcp_hand.w;
|
||||
tcp_hand.h = tcp_hand.h;
|
||||
tcp_hand.frame_rate = 25;
|
||||
tcp_hand.ip_grp = 25;
|
||||
tcp_hand.packet_len = MAX_VIDEO_PKT_LEN;
|
||||
ret = send(tcp_fd,&tcp_hand,sizeof(tcp_hand),0);
|
||||
BABY_DBG("set tcp cfg:%d\r\n",ret);
|
||||
}else if(tcp_hand.type == 0){
|
||||
BABY_DBG("tcp get cfg:%d\r\n",tcp_hand.dev_magic);
|
||||
if(tcp_hand.dev_magic == 0){ //新设备刚开机
|
||||
tcp_hand.type = 2;
|
||||
tcp_hand.w = 640;//640;
|
||||
tcp_hand.h = 360;//360;
|
||||
tcp_hand.frame_rate = 20;
|
||||
tcp_hand.ip_grp = 25;
|
||||
tcp_hand.packet_len = MAX_VIDEO_PKT_LEN;
|
||||
tcp_hand.dev_magic = 0;
|
||||
for(itk = 0;itk < 10;itk++){
|
||||
if(tcp_fd == devtab[itk].tcpfd){
|
||||
if(devtab[itk].dev_id != 0){
|
||||
tcp_hand.dev_magic = devtab[itk].dev_id;
|
||||
}
|
||||
|
||||
ip = devtab[itk].ipaddr;
|
||||
}
|
||||
}
|
||||
|
||||
if(tcp_hand.dev_magic == 0){
|
||||
tcp_hand.dev_magic = ((ip>>24)&(STA_NUM-1)) + 1; //控制设备编号
|
||||
}
|
||||
|
||||
|
||||
ret = send(tcp_fd,&tcp_hand,sizeof(tcp_hand),0);
|
||||
BABY_DBG("start client run:%d\r\n",ret);
|
||||
|
||||
}else{ //这个设备已经开机过了
|
||||
for(itk = 0;itk < 10;itk++){
|
||||
if(tcp_fd == devtab[itk].tcpfd){
|
||||
devtab[itk].dev_id = tcp_hand.dev_magic;
|
||||
devtab[itk].frame_rate = tcp_hand.frame_rate;
|
||||
devtab[itk].w = tcp_hand.w;
|
||||
devtab[itk].h = tcp_hand.h;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(tcp_hand.type == 1){ //client心跳包
|
||||
BABY_DBG("heartbeat...\r\n");
|
||||
for(itk = 0;itk < 10;itk++){
|
||||
if(tcp_hand.dev_magic == devtab[itk].dev_id){ //查看client的心跳包是否有记录在table中
|
||||
//magic id存在,但与设备号的不匹配
|
||||
for(jtk = 0;jtk < 10;jtk++){
|
||||
if(tcp_fd == devtab[jtk].tcpfd){
|
||||
ip = devtab[jtk].ipaddr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
os_printf("check ip addr(%d %08x %d)",tcp_fd,ip,tcp_hand.dev_magic);
|
||||
if((((ip>>24)&(STA_NUM-1)) + 1) != tcp_hand.dev_magic){ //根据ip地址分配的设备号匹配不上,那得给对面设备重新配置
|
||||
tcp_hand.type = 5;
|
||||
tcp_hand.dev_magic = ((ip>>24)&(STA_NUM-1)) + 1;
|
||||
ret = send(tcp_fd,&tcp_hand,sizeof(tcp_hand),0);
|
||||
BABY_DBG("reset devid:%d ip:%x set id:%d\r\n",ret,ip,tcp_hand.dev_magic);
|
||||
maskid = tcp_hand.dev_magic;
|
||||
dev = maskid;
|
||||
}else{
|
||||
maskid = tcp_hand.dev_magic;
|
||||
devtab[itk].w = tcp_hand.w; //更新心跳过来的设备长度
|
||||
devtab[itk].h = tcp_hand.h;
|
||||
dev = maskid;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(maskid == 0){ //client心跳有,但table中却没有此信息
|
||||
for(itk = 0;itk < 10;itk++){
|
||||
if(tcp_fd == devtab[itk].tcpfd){
|
||||
devtab[itk].dev_id = tcp_hand.dev_magic; //把当前设备号记录下来
|
||||
devtab[itk].frame_rate = tcp_hand.frame_rate;
|
||||
devtab[itk].w = tcp_hand.w;
|
||||
devtab[itk].h = tcp_hand.h;
|
||||
devtab[itk].psram_photo = av_psram_malloc(200*1024); //给初始化空间 200K
|
||||
dev = devtab[itk].dev_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//dev是对面给过来的,这里是心跳包,对方肯定已经开机并且有了设备号
|
||||
dev--; //设备是从1开始,所以这里得--
|
||||
if((server_resolution[dev].target_width != devtab[itk].w) || (server_resolution[dev].target_high != devtab[itk].h)) {
|
||||
tcp_hand.type = 2;
|
||||
tcp_hand.w = server_resolution[dev].target_width;
|
||||
tcp_hand.h = server_resolution[dev].target_high;
|
||||
tcp_hand.frame_rate = 20;
|
||||
tcp_hand.ip_grp = 25;
|
||||
tcp_hand.packet_len = MAX_VIDEO_PKT_LEN;
|
||||
ret = send(tcp_fd,&tcp_hand,sizeof(tcp_hand),0);
|
||||
}
|
||||
//分辨率切换操作
|
||||
#if 0
|
||||
//if(test_recfg == 0)
|
||||
{
|
||||
test_recfg++;
|
||||
//if(os_jiffies() > 10000)
|
||||
if(test_recfg % 30 == 19)
|
||||
{
|
||||
os_printf("recfg size(%d)...\r\n",dev);
|
||||
tcp_hand.type = 2;
|
||||
if(tcp_hand.w == 1280){
|
||||
tcp_hand.w = 640;
|
||||
tcp_hand.h = 360;
|
||||
server_resolution[dev].target_width = 640;
|
||||
server_resolution[dev].target_high = 360;
|
||||
}else{
|
||||
tcp_hand.w = 1280;
|
||||
tcp_hand.h = 720;
|
||||
server_resolution[dev].target_width = 1280;
|
||||
server_resolution[dev].target_high = 720;
|
||||
}
|
||||
|
||||
tcp_hand.frame_rate = 20;
|
||||
tcp_hand.ip_grp = 25;
|
||||
tcp_hand.packet_len = MAX_VIDEO_PKT_LEN;
|
||||
ret = send(tcp_fd,&tcp_hand,sizeof(tcp_hand),0);
|
||||
//test_recfg = 1;
|
||||
}else if(test_recfg % 60 == 26){
|
||||
_os_printf("recfg size2(%d)...\r\n",dev);
|
||||
tcp_hand.type = 2;
|
||||
if(tcp_hand.w == 1280){
|
||||
tcp_hand.w = 640;
|
||||
tcp_hand.h = 360;
|
||||
server_resolution[dev].target_width = 640;
|
||||
server_resolution[dev].target_high = 360;
|
||||
}else{
|
||||
tcp_hand.w = 1280;
|
||||
tcp_hand.h = 720;
|
||||
server_resolution[dev].target_width = 1280;
|
||||
server_resolution[dev].target_high = 720;
|
||||
}
|
||||
tcp_hand.frame_rate = 20;
|
||||
tcp_hand.ip_grp = 25;
|
||||
tcp_hand.packet_len = MAX_VIDEO_PKT_LEN;
|
||||
ret = send(tcp_fd,&tcp_hand,sizeof(tcp_hand),0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}else{
|
||||
BABY_DBG("tcp read close fd....\r\n");
|
||||
eloop_remove_event( ei );
|
||||
closesocket( tcp_fd );
|
||||
for(itk = 0;itk < 10;itk++){
|
||||
if(tcp_fd == devtab[itk].tcpfd){ //释放的FD是存在于table表的,确定没有进行重新连接
|
||||
devtab[itk].tcpfd = 0;
|
||||
devtab[itk].ipaddr= 0;
|
||||
devtab[itk].dev_id= 0;
|
||||
devtab[itk].frame_rate = 0;
|
||||
av_psram_free(devtab[itk].psram_photo);
|
||||
devtab[itk].psram_photo = NULL;
|
||||
tab_idx = itk;
|
||||
}
|
||||
}
|
||||
devnum--;
|
||||
tcp_fd = -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void user_tcpServerAccept(void *e, void *d) //屏端
|
||||
{
|
||||
uint8_t itk=0;
|
||||
uint8_t dnum = 0;
|
||||
uint8_t mask = 0;
|
||||
// connect_cfg_head tcp_hand;
|
||||
// k_task_handle_t task_hdl;
|
||||
struct sockaddr_in client;
|
||||
socklen_t addrlen;
|
||||
// int32 ret;
|
||||
addrlen =sizeof(client);
|
||||
int tcp_fd = accept(tcp_connect_fd, (struct sockaddr*)&client, &addrlen);
|
||||
if(tcp_fd < 0)
|
||||
{
|
||||
BABY_DBG("accept()error...............\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for(itk = 0;itk < 10;itk++){
|
||||
if(devtab[itk].ipaddr == client.sin_addr.s_addr){ //发现当前列表里面已经有此IP地址
|
||||
devtab[itk].tcpfd = tcp_fd; //更新此列表的fd
|
||||
mask = 1; //标识,表明当前IP已有设备id分配
|
||||
}
|
||||
}
|
||||
if(mask == 0){ //当前IP没被分配
|
||||
for(itk = 0;itk < 10;itk++){
|
||||
if(devtab[itk].tcpfd == 0){
|
||||
dnum = itk;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
devtab[dnum].ipaddr = client.sin_addr.s_addr;
|
||||
devtab[dnum].tcpfd = tcp_fd;
|
||||
devnum++; //标明下个设备号
|
||||
}
|
||||
|
||||
eloop_add_fd( tcp_fd, EVENT_READ, EVENT_F_ENABLED, tcp_handle_server, (void*)tcp_fd );
|
||||
}
|
||||
|
||||
|
||||
void tcp_handle_server_init(){
|
||||
int InitSrv(uint16_t port);
|
||||
tcp_connect_fd = InitSrv(6001);
|
||||
eloop_add_fd( tcp_connect_fd, EVENT_READ, EVENT_F_ENABLED, user_tcpServerAccept, 0 );
|
||||
}
|
||||
|
||||
void protocol_server_init(){
|
||||
uint8_t i = 0;
|
||||
struct h264_device *h264_dev;
|
||||
struct msi *scale2 = scale2_msi("scale2", 640, 360, 640, 360, FSTYPE_YUV_P0, 10);
|
||||
if (scale2)
|
||||
{
|
||||
msi_add_output(scale2, NULL, R_VIDEO_P0);
|
||||
msi_add_output(scale2, NULL, R_VIDEO_P1);
|
||||
os_printf("%s %d\r\n",__func__,__LINE__);
|
||||
}
|
||||
|
||||
for(i = 0;i < STA_NUM;i++){
|
||||
server_resolution[i].target_width = 1280;
|
||||
server_resolution[i].target_high = 720;
|
||||
}
|
||||
|
||||
//scaler_msi_gol = scale2;
|
||||
h264_dev = (struct h264_device *)dev_get(HG_H264_DEVID);
|
||||
memset(decmsg,0x00,sizeof(decmsg));
|
||||
for(i=0; i<10; i++) {
|
||||
devtab[i].larger = 10;
|
||||
}
|
||||
h264_drv_init(h264_dev);
|
||||
h264_dec_room_init(2,1280,720);
|
||||
net_h264_sema_init();
|
||||
udp_handle_server_init();
|
||||
tcp_handle_server_init();
|
||||
}
|
||||
|
||||
void protocol_server_change_resolution(uint8_t id, uint32_t width, uint32_t high)
|
||||
{
|
||||
server_resolution[id].target_width = width;
|
||||
server_resolution[id].target_high = high;
|
||||
}
|
||||
|
||||
void user_protocol()
|
||||
{
|
||||
os_sleep_ms(100);
|
||||
protocol_server_init(); //进行推屏 AP
|
||||
}
|
||||
|
||||
static void babyprotocol_switch_device(int8_t device)
|
||||
{
|
||||
next_switch_device = device;
|
||||
}
|
||||
|
||||
int32_t atcmd_babyprotocol_switch_device(const char *cmd, char *argv[], uint32 argc)
|
||||
{
|
||||
int8_t device = 0;
|
||||
if(argv[0]) {
|
||||
device = os_atoi(argv[0]);
|
||||
babyprotocol_switch_device(device);
|
||||
return RET_OK;
|
||||
}
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
static void babyprotocol_change_larger(uint8_t device, uint8_t larger)
|
||||
{
|
||||
devtab[device].larger = larger;
|
||||
}
|
||||
|
||||
int32_t atcmd_babyprotocol_change_larger(const char *cmd, char *argv[], uint32 argc)
|
||||
{
|
||||
if(argc >= 2) {
|
||||
uint8_t device = os_atoi(argv[0]);
|
||||
uint8_t larger = os_atoi(argv[1]);
|
||||
babyprotocol_change_larger(device, larger);
|
||||
return RET_OK;
|
||||
}
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
#endif
|
||||
137
sdk/app/battery_adc_detect/battery_det.c
Normal file
137
sdk/app/battery_adc_detect/battery_det.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "basic_include.h"
|
||||
#include "dev/adc/hgadc_v0.h"
|
||||
#ifdef PIN_FROM_PARAM
|
||||
#include "pin_param.h"
|
||||
#endif
|
||||
#include "lib/lmac/lmac.h"
|
||||
|
||||
struct bat_det_priv {
|
||||
struct os_work work;
|
||||
struct hgadc_v0 *adc_dev;
|
||||
uint32_t bat_det_io;
|
||||
float vol;
|
||||
uint32_t _update_fme_adc_val;
|
||||
uint8_t level;
|
||||
uint8_t get_value;
|
||||
uint32_t adc_raw;
|
||||
};
|
||||
|
||||
struct bat_det_priv *g_bat_det_priv_data = NULL;
|
||||
|
||||
static int32 bat_detect_work(struct os_work *work)
|
||||
{
|
||||
#if WIFI_FEM_CHIP
|
||||
void * ops = NULL;
|
||||
#endif
|
||||
|
||||
struct bat_det_priv *bat_det_priv_data = (struct bat_det_priv *)work;
|
||||
|
||||
uint32_t adc_value = 0;
|
||||
|
||||
adc_get_value((struct adc_device *)bat_det_priv_data->adc_dev, bat_det_priv_data->bat_det_io, &adc_value);
|
||||
|
||||
bat_det_priv_data->adc_raw = adc_value;
|
||||
bat_det_priv_data->get_value = 1;
|
||||
|
||||
bat_det_priv_data->vol = (float)adc_value * 3 / 2048 * 2;
|
||||
|
||||
bat_det_priv_data->_update_fme_adc_val = adc_value * 3 * 2 / 5;
|
||||
if (bat_det_priv_data->_update_fme_adc_val > 2047) {
|
||||
bat_det_priv_data->_update_fme_adc_val = 2047;
|
||||
}
|
||||
|
||||
os_printf("---- battery adc:%d vol:%.2fV _update_fme_adc_val:%.2fV adc_val:%d----\n", adc_value, (float)adc_value * 3 / 2048 * 2, (float)bat_det_priv_data->_update_fme_adc_val * 5 / 2048, bat_det_priv_data->_update_fme_adc_val);
|
||||
|
||||
// bat_det_priv_data->vol = 4;
|
||||
#if WIFI_FEM_CHIP
|
||||
lmac_update_fem_voltage(ops, (uint32_t)(5 * (1 << 10)));
|
||||
#endif
|
||||
|
||||
os_run_work_delay(&bat_det_priv_data->work, 5000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bat_get_level()
|
||||
{
|
||||
/* 如果未初始化,返回0 */
|
||||
if (!g_bat_det_priv_data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 使用 ADC 阈值表
|
||||
阈值单位为 ADC 读数,避免浮点运算。加入整型 hysteresis 防跳变。 */
|
||||
uint8_t res = 0;
|
||||
static uint8_t first_count = 1;
|
||||
static const uint16_t thresholds_adc[] = {1125, 1185, 1245, 1305, 1365};
|
||||
const int max_level = sizeof(thresholds_adc) / sizeof(thresholds_adc[0]);
|
||||
const uint16_t hysteresis_adc = 10; /* ADC 单位去抖 */
|
||||
|
||||
uint32_t adc = g_bat_det_priv_data->adc_raw;
|
||||
|
||||
/* 计算候选等级 */
|
||||
int cand = 0;
|
||||
if(g_bat_det_priv_data->get_value == 0) {
|
||||
return 4;
|
||||
}
|
||||
while (cand < max_level && adc > thresholds_adc[cand]) {
|
||||
cand++;
|
||||
}
|
||||
if (cand > (max_level - 1)) {
|
||||
cand = max_level - 1;
|
||||
}
|
||||
|
||||
if (first_count) {
|
||||
first_count = 0;
|
||||
g_bat_det_priv_data->level = (uint8_t)cand;
|
||||
return cand;
|
||||
}
|
||||
|
||||
int prev = (int)g_bat_det_priv_data->level;
|
||||
if (cand == prev) {
|
||||
return (uint8_t)prev;
|
||||
}
|
||||
|
||||
if (cand > prev) {
|
||||
/* 上升:需要超过阈值 + hysteresis 才更新 */
|
||||
if (adc >= (uint32_t)thresholds_adc[prev] + hysteresis_adc) {
|
||||
g_bat_det_priv_data->level = (uint8_t)cand;
|
||||
res = (uint8_t)cand;
|
||||
} else {
|
||||
res = (uint8_t)prev;
|
||||
}
|
||||
} else { /* cand < prev */
|
||||
/* 下降:需要低于阈值 - hysteresis 才更新 */
|
||||
if (adc <= (uint32_t)thresholds_adc[prev] - hysteresis_adc) {
|
||||
g_bat_det_priv_data->level = (uint8_t)cand;
|
||||
res = (uint8_t)cand;
|
||||
} else {
|
||||
res = (uint8_t)prev;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void bat_ad_init()
|
||||
{
|
||||
struct bat_det_priv *bat_det_priv_data = (struct bat_det_priv*)os_zalloc(sizeof(struct bat_det_priv));
|
||||
|
||||
if (!bat_det_priv_data) {
|
||||
os_printf("bat ad init err!!!!!!!!!!!!!\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
g_bat_det_priv_data = bat_det_priv_data;
|
||||
|
||||
bat_det_priv_data->adc_dev = (struct hgadc_v0*)dev_get(HG_ADC0_DEVID);
|
||||
bat_det_priv_data->bat_det_io = MACRO_PIN(BAT_ADC_IO);
|
||||
|
||||
adc_open((struct adc_device *)bat_det_priv_data->adc_dev);
|
||||
|
||||
gpio_set_mode(bat_det_priv_data->bat_det_io, GPIO_PULL_NONE, GPIO_PULL_LEVEL_NONE);
|
||||
|
||||
adc_add_channel((struct adc_device *)bat_det_priv_data->adc_dev, bat_det_priv_data->bat_det_io);
|
||||
|
||||
OS_WORK_INIT(&bat_det_priv_data->work, bat_detect_work, 0);
|
||||
os_run_work_delay(&bat_det_priv_data->work, 1000);
|
||||
}
|
||||
7
sdk/app/battery_adc_detect/battery_det.h
Normal file
7
sdk/app/battery_adc_detect/battery_det.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef __BATTERY_DET_H_
|
||||
#define __BATTERY_DET_H_
|
||||
|
||||
void bat_ad_init();
|
||||
int bat_get_level();
|
||||
|
||||
#endif
|
||||
285
sdk/app/debug_log_msi/debug_log_msi.c
Normal file
285
sdk/app/debug_log_msi/debug_log_msi.c
Normal file
@@ -0,0 +1,285 @@
|
||||
// 主要是增加debug流,可以保存log到内存,然后发向流,可以作为定时保存log使用
|
||||
// 这个流就不作保护,所以最好单线程去使用(如果多线程,可以增加锁),可以使用一个
|
||||
// 全局去保存对应的句柄,但是这里就不全局保存也不使用全局(可以创建多个流,每个
|
||||
// 独立的线程可以独立调试)
|
||||
#include "debug_log_msi.h"
|
||||
|
||||
#define DEBUG_LOG_STREAM_MALLOC av_psram_malloc
|
||||
#define DEBUG_LOG_STREAM_FREE av_psram_free
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define DEBUG_LOG_MAX_NUM 10
|
||||
#define DEBUG_LOG_CACHE_SIZE (1024 * 4) // 4K
|
||||
|
||||
#define DBG_LOG_FAIL_TIMES (3)
|
||||
|
||||
static int32_t debug_log_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct dbg_log_s *log_s = (struct dbg_log_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
fbpool_destroy(&log_s->tx_pool);
|
||||
if (log_s)
|
||||
{
|
||||
STREAM_LIBC_FREE(log_s);
|
||||
msi->priv = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
if (log_s)
|
||||
{
|
||||
os_work_cancle2(&log_s->work, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
if (fb->data)
|
||||
{
|
||||
DEBUG_LOG_STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
fb->rev = 0;
|
||||
fbpool_put(&log_s->tx_pool, fb);
|
||||
// 不需要内核去释放fb
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t sync_debug_buf(struct dbg_log_s *log_s)
|
||||
{
|
||||
uint32_t flags;
|
||||
int ret = 0;
|
||||
|
||||
struct framebuff *fb = NULL;
|
||||
|
||||
flags = disable_irq();
|
||||
if (log_s->fb && log_s->offset)
|
||||
{
|
||||
fb = log_s->fb;
|
||||
fb->len = log_s->offset;
|
||||
log_s->fb = NULL;
|
||||
log_s->offset = 0;
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
if (fb)
|
||||
{
|
||||
ret = fb->len;
|
||||
msi_output_fb(log_s->s, fb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32 debug_log_sync_work(struct os_work *work)
|
||||
{
|
||||
struct dbg_log_s *log_s = (struct dbg_log_s *) work;
|
||||
sync_debug_buf(log_s);
|
||||
os_run_work_delay(work, 1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *dbg_log_msi(const char *host_name)
|
||||
{
|
||||
struct msi *s = NULL;
|
||||
uint8_t isnew;
|
||||
struct dbg_log_s *log_s;
|
||||
s = msi_new(host_name, 0, &isnew);
|
||||
|
||||
if (isnew)
|
||||
{
|
||||
log_s = (struct dbg_log_s *) STREAM_LIBC_ZALLOC(sizeof(struct dbg_log_s));
|
||||
ASSERT(log_s);
|
||||
s->priv = (void *) log_s;
|
||||
s->action = (msi_action) debug_log_action;
|
||||
fbpool_init(&log_s->tx_pool, DEBUG_LOG_MAX_NUM);
|
||||
log_s->s = s;
|
||||
log_s->fb = NULL;
|
||||
log_s->offset = 0;
|
||||
OS_WORK_INIT(&log_s->work, debug_log_sync_work, 0);
|
||||
os_run_work_delay(&log_s->work, 1000);
|
||||
msi_add_output(s, NULL, R_DEBUG_STREAM);
|
||||
s->enable = 1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
uint8_t *get_debug_buf(struct dbg_log_s *log_s, uint32_t *write_len, uint32_t len)
|
||||
{
|
||||
uint8_t *malloc_buf;
|
||||
uint8_t *buf;
|
||||
uint32_t remain_size;
|
||||
uint32_t flags;
|
||||
uint8_t disable_irq_en = 0;
|
||||
uint32_t times = 0;
|
||||
|
||||
struct framebuff *fb = NULL;
|
||||
|
||||
again:
|
||||
flags = disable_irq();
|
||||
if (log_s->fb && (DEBUG_LOG_CACHE_SIZE == log_s->offset))
|
||||
{
|
||||
fb = log_s->fb;
|
||||
fb->len = log_s->offset;
|
||||
log_s->fb = NULL;
|
||||
log_s->offset = 0;
|
||||
}
|
||||
enable_irq(flags);
|
||||
|
||||
if (fb)
|
||||
{
|
||||
msi_output_fb(log_s->s, fb);
|
||||
}
|
||||
|
||||
if (!log_s->fb)
|
||||
{
|
||||
malloc_buf = (uint8_t *) DEBUG_LOG_STREAM_MALLOC(DEBUG_LOG_CACHE_SIZE);
|
||||
if (malloc_buf)
|
||||
{
|
||||
flags = disable_irq();
|
||||
disable_irq_en = 1;
|
||||
if (!log_s->fb)
|
||||
{
|
||||
log_s->fb = fbpool_get(&log_s->tx_pool, 0, log_s->s);
|
||||
if (log_s->fb)
|
||||
{
|
||||
log_s->fb->data = malloc_buf;
|
||||
log_s->offset = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG_STREAM_FREE(malloc_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有关闭中断,就关闭中断去操?因为log_s->fb有可能需要同步,会被释放
|
||||
if (!disable_irq_en)
|
||||
{
|
||||
flags = disable_irq();
|
||||
disable_irq_en = 1;
|
||||
}
|
||||
if (log_s->fb)
|
||||
{
|
||||
buf = log_s->fb->data + log_s->offset;
|
||||
remain_size = DEBUG_LOG_CACHE_SIZE - log_s->offset;
|
||||
if (remain_size > len)
|
||||
{
|
||||
*write_len = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*write_len = remain_size;
|
||||
}
|
||||
|
||||
log_s->offset += (*write_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
*write_len = 0;
|
||||
buf = NULL;
|
||||
}
|
||||
if (disable_irq_en)
|
||||
{
|
||||
enable_irq(flags);
|
||||
}
|
||||
times++;
|
||||
// 如果保存失败,重新去尝试吧
|
||||
if (!buf && (times < DBG_LOG_FAIL_TIMES))
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
goto again;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
uint8_t *get_debug_buf_interrupt(struct dbg_log_s *log_s, uint32_t *write_len, uint32_t len)
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint32_t remain_size;
|
||||
//uint32_t flags;
|
||||
if (log_s->fb)
|
||||
{
|
||||
buf = log_s->fb->data + log_s->offset;
|
||||
remain_size = DEBUG_LOG_CACHE_SIZE - log_s->offset;
|
||||
if (remain_size >= len)
|
||||
{
|
||||
*write_len = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*write_len = remain_size;
|
||||
log_s->fb->rev = 1; // 标记有数据漏了,log那里可以记录一下
|
||||
}
|
||||
if (!remain_size)
|
||||
{
|
||||
*write_len = 0;
|
||||
buf = NULL;
|
||||
}
|
||||
log_s->offset += (*write_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
*write_len = 0;
|
||||
buf = NULL;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void hgprntf_debug_log_msi(void *priv, char *str, int32 len)
|
||||
{
|
||||
uint32_t in_disable_irq(void);
|
||||
uint8_t *buf;
|
||||
struct dbg_log_s *log_s = (struct dbg_log_s *) priv;
|
||||
if (__in_interrupt() || in_disable_irq())
|
||||
{
|
||||
uint32_t cp_len;
|
||||
if (len == 0)
|
||||
{
|
||||
len = os_strlen(str);
|
||||
}
|
||||
buf = get_debug_buf_interrupt(log_s, &cp_len, len);
|
||||
if (buf)
|
||||
{
|
||||
os_memcpy(buf, str, cp_len);
|
||||
len -= cp_len;
|
||||
str += cp_len;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
len = os_strlen(str);
|
||||
}
|
||||
do
|
||||
{
|
||||
uint32_t cp_len;
|
||||
buf = get_debug_buf(log_s, &cp_len, len);
|
||||
if (buf)
|
||||
{
|
||||
os_memcpy(buf, str, cp_len);
|
||||
len -= cp_len;
|
||||
str += cp_len;
|
||||
}
|
||||
} while (len && buf);
|
||||
}
|
||||
20
sdk/app/debug_log_msi/debug_log_msi.h
Normal file
20
sdk/app/debug_log_msi/debug_log_msi.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __DEBUG_LOG_STREAM_H
|
||||
#define __DEBUG_LOG_STREAM_H
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "stream_frame.h"
|
||||
|
||||
struct dbg_log_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *s;
|
||||
struct framebuff *fb; //当前的data_s
|
||||
struct fbpool tx_pool;
|
||||
uint32_t offset; //当前数据的偏移,最大值是cache_data_size
|
||||
};
|
||||
|
||||
void hgprntf_debug_log_msi(void *priv, char *str, int32 len);
|
||||
void *dbg_log_msi(const char *host_name);
|
||||
#endif
|
||||
292
sdk/app/debug_log_msi/log_save_msi.c
Normal file
292
sdk/app/debug_log_msi/log_save_msi.c
Normal file
@@ -0,0 +1,292 @@
|
||||
#include "log_save_msi.h"
|
||||
|
||||
// 接收debug_stream的log保存到sd卡
|
||||
#define LOG_MALLOC av_psram_malloc
|
||||
#define LOG_FREE av_psram_free
|
||||
|
||||
#define LOG_SIZE_UINT (100 * 1024)
|
||||
#define SAVE_RESERVE_SIZE (10 + 1 + 8 + 1)
|
||||
#define SAVE_FLAG_FORMAT "[%08d]:log end\n"
|
||||
#define WRITE_DROP_DATA_FLAG "[%08d]:interrupt drop\n"
|
||||
|
||||
#define LOG_SAVE_PATH "0:log"
|
||||
static int32 log_save_work(struct os_work *work)
|
||||
{
|
||||
struct log_save_s *log_s = (struct log_save_s *) work;
|
||||
struct framebuff *get_f;
|
||||
struct msi *s = log_s->s;
|
||||
uint32_t tell = 0;
|
||||
char filename[64];
|
||||
int ret = 0;
|
||||
|
||||
// 尝试接收数据,看看是否有需要写入到sd卡或者缓冲区buf
|
||||
get_f = msi_get_fb(s, 0);
|
||||
if (get_f && get_f->rev != 0)
|
||||
{
|
||||
log_s->drop_data_flag = 1;
|
||||
}
|
||||
if (get_f)
|
||||
{
|
||||
uint32_t write_cache_size = get_f->len;
|
||||
// 要先判断缓冲区是否足够空间,如果不够,则先将缓冲区写入到sd卡,然后再将数据拷贝到缓冲区
|
||||
if (log_s->start_offset + log_s->offset + write_cache_size + SAVE_RESERVE_SIZE > CACHE_SIZE)
|
||||
{
|
||||
// 将当前缓冲区写入sd卡,然后再将数据拷贝到缓冲区
|
||||
if (!log_s->fp)
|
||||
{
|
||||
struct tm *time_info;
|
||||
struct timeval ptimeval;
|
||||
gettimeofday(&ptimeval, NULL);
|
||||
time_t time_val = (time_t) ptimeval.tv_sec;
|
||||
|
||||
time_info = gmtime(&time_val);
|
||||
|
||||
uint32_t year = time_info->tm_year + 1900;
|
||||
uint32_t mon = time_info->tm_mon + 1;
|
||||
uint32_t day = time_info->tm_mday;
|
||||
uint32_t hour = time_info->tm_hour;
|
||||
uint32_t min = time_info->tm_min;
|
||||
uint32_t sec = time_info->tm_sec;
|
||||
uint32_t ms = os_jiffies() % 1000;
|
||||
|
||||
os_sprintf((char *) filename, "%s/%04d%02d%02d%02d%02d%02d%03d.txt", LOG_SAVE_PATH, year, mon, day, hour, min, sec, ms);
|
||||
log_s->fp = osal_fopen_auto((const char *) filename, "wb", 0);
|
||||
log_s->filesize = 0;
|
||||
if (log_s->fp)
|
||||
{
|
||||
log_s->filesize = LOG_SIZE_UINT;
|
||||
|
||||
tell = osal_ftell(log_s->fp);
|
||||
// 预分配文件簇
|
||||
osal_fseek(log_s->fp, log_s->filesize);
|
||||
osal_fseek(log_s->fp, tell);
|
||||
}
|
||||
|
||||
log_s->lastupdate_file_time = os_jiffies();
|
||||
log_s->last_syn_time = os_jiffies();
|
||||
}
|
||||
|
||||
if (log_s->fp)
|
||||
{
|
||||
tell = osal_ftell(log_s->fp);
|
||||
if (log_s->filesize < tell + log_s->offset)
|
||||
{
|
||||
log_s->filesize += LOG_SIZE_UINT;
|
||||
}
|
||||
// 预分配文件簇
|
||||
osal_fseek(log_s->fp, log_s->filesize);
|
||||
osal_fseek(log_s->fp, tell);
|
||||
// 如果有漏数据,则在这里写入一个特殊标志,代表曾经漏过数据,不保证漏数据多少,只是一个标志
|
||||
if (log_s->drop_data_flag)
|
||||
{
|
||||
os_sprintf(filename, WRITE_DROP_DATA_FLAG, (uint32_t) os_jiffies());
|
||||
osal_fwrite(filename, strlen(filename), 1, log_s->fp);
|
||||
log_s->drop_data_flag = 0;
|
||||
}
|
||||
ret = osal_fwrite(log_s->save_buf + log_s->start_offset, log_s->offset + SAVE_RESERVE_SIZE, 1, log_s->fp);
|
||||
tell = osal_ftell(log_s->fp);
|
||||
osal_fseek(log_s->fp, tell - SAVE_RESERVE_SIZE);
|
||||
if (!ret)
|
||||
{
|
||||
osal_ftruncate(log_s->fp);
|
||||
osal_fclose(log_s->fp);
|
||||
log_s->fp = NULL;
|
||||
}
|
||||
log_s->start_offset = 0;
|
||||
log_s->offset = 0;
|
||||
}
|
||||
|
||||
// 重新将获取到的数据保存到save_buf,可能要考虑没有sd卡的情况?
|
||||
// 没有sd卡,直接丢弃?
|
||||
// 理论这里offset一定是从0开始
|
||||
if (log_s->fp)
|
||||
{
|
||||
// 判断当前位置,调整start_offset,作为对齐使用
|
||||
uint32_t tell = osal_ftell(log_s->fp);
|
||||
log_s->start_offset = 4 - tell % 4;
|
||||
hw_memcpy(log_s->save_buf + log_s->start_offset + log_s->offset, get_f->data, write_cache_size);
|
||||
os_sprintf((char *) log_s->save_buf + log_s->start_offset + log_s->offset + write_cache_size, SAVE_FLAG_FORMAT, osal_ftell(log_s->fp));
|
||||
log_s->offset = write_cache_size;
|
||||
}
|
||||
}
|
||||
// 缓冲区足够,直接拷贝
|
||||
else
|
||||
{
|
||||
// 将当前缓冲区写入sd卡,然后再将数据拷贝到缓冲区
|
||||
if (!log_s->fp)
|
||||
{
|
||||
struct tm *time_info;
|
||||
struct timeval ptimeval;
|
||||
gettimeofday(&ptimeval, NULL);
|
||||
time_t time_val = (time_t) ptimeval.tv_sec;
|
||||
|
||||
time_info = gmtime(&time_val);
|
||||
|
||||
uint32_t year = time_info->tm_year + 1900;
|
||||
uint32_t mon = time_info->tm_mon + 1;
|
||||
uint32_t day = time_info->tm_mday;
|
||||
uint32_t hour = time_info->tm_hour;
|
||||
uint32_t min = time_info->tm_min;
|
||||
uint32_t sec = time_info->tm_sec;
|
||||
uint32_t ms = os_jiffies() % 1000;
|
||||
|
||||
os_sprintf((char *) filename, "%s/%04d%02d%02d%02d%02d%02d%03d.txt", LOG_SAVE_PATH, year, mon, day, hour, min, sec, ms);
|
||||
log_s->fp = osal_fopen_auto((const char *) filename, "wb", 0);
|
||||
log_s->filesize = 0;
|
||||
|
||||
log_s->lastupdate_file_time = os_jiffies();
|
||||
log_s->last_syn_time = os_jiffies();
|
||||
}
|
||||
|
||||
if (log_s->fp)
|
||||
{
|
||||
hw_memcpy(log_s->save_buf + log_s->start_offset + log_s->offset, get_f->data, write_cache_size);
|
||||
os_sprintf((char *) log_s->save_buf + log_s->start_offset + log_s->offset + write_cache_size, SAVE_FLAG_FORMAT, osal_ftell(log_s->fp) + log_s->offset + write_cache_size);
|
||||
log_s->offset += write_cache_size;
|
||||
}
|
||||
}
|
||||
|
||||
msi_delete_fb(NULL, get_f);
|
||||
}
|
||||
|
||||
// 如果存在文件,要判断是否需要更换文件保存log
|
||||
if (log_s->fp && (os_jiffies() - log_s->lastupdate_file_time > log_s->update_file_interval))
|
||||
{
|
||||
if (log_s->offset)
|
||||
{
|
||||
// 如果有漏数据,则在这里写入一个特殊标志,代表曾经漏过数据,不保证漏数据多少,只是一个标志
|
||||
if (log_s->drop_data_flag)
|
||||
{
|
||||
os_sprintf(filename, WRITE_DROP_DATA_FLAG, (uint32_t) os_jiffies());
|
||||
osal_fwrite(filename, strlen(filename), 1, log_s->fp);
|
||||
log_s->drop_data_flag = 0;
|
||||
}
|
||||
osal_fwrite(log_s->save_buf + log_s->start_offset, log_s->offset, 1, log_s->fp);
|
||||
}
|
||||
log_s->last_syn_time = os_jiffies();
|
||||
log_s->lastupdate_file_time = os_jiffies();
|
||||
osal_ftruncate(log_s->fp);
|
||||
osal_fclose(log_s->fp);
|
||||
log_s->fp = NULL;
|
||||
log_s->start_offset = 0;
|
||||
log_s->offset = 0;
|
||||
}
|
||||
|
||||
// 先判断是否要切换下一个文件去记录log
|
||||
// 去同步一下
|
||||
if (os_jiffies() - log_s->last_syn_time > log_s->syn_interval)
|
||||
{
|
||||
if (log_s->fp)
|
||||
{
|
||||
if (log_s->offset)
|
||||
{
|
||||
if (log_s->fp)
|
||||
{
|
||||
tell = osal_ftell(log_s->fp);
|
||||
if (log_s->filesize < tell + log_s->offset)
|
||||
{
|
||||
log_s->filesize += LOG_SIZE_UINT;
|
||||
}
|
||||
// 预分配文件簇
|
||||
osal_fseek(log_s->fp, log_s->filesize);
|
||||
osal_fseek(log_s->fp, tell);
|
||||
}
|
||||
|
||||
// 如果有漏数据,则在这里写入一个特殊标志,代表曾经漏过数据,不保证漏数据多少,只是一个标志
|
||||
if (log_s->drop_data_flag)
|
||||
{
|
||||
os_sprintf(filename, WRITE_DROP_DATA_FLAG, (uint32_t) os_jiffies());
|
||||
osal_fwrite(filename, strlen(filename), 1, log_s->fp);
|
||||
log_s->drop_data_flag = 0;
|
||||
}
|
||||
ret = osal_fwrite(log_s->save_buf + log_s->start_offset, log_s->offset + SAVE_RESERVE_SIZE, 1, log_s->fp);
|
||||
tell = osal_ftell(log_s->fp);
|
||||
osal_fseek(log_s->fp, tell - SAVE_RESERVE_SIZE);
|
||||
tell = osal_ftell(log_s->fp);
|
||||
if (!ret)
|
||||
{
|
||||
osal_ftruncate(log_s->fp);
|
||||
osal_fclose(log_s->fp);
|
||||
log_s->fp = NULL;
|
||||
goto __log_save_work_end;
|
||||
}
|
||||
log_s->start_offset = 0;
|
||||
log_s->offset = 0;
|
||||
}
|
||||
osal_fsync(log_s->fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_s->start_offset = 0;
|
||||
log_s->offset = 0;
|
||||
}
|
||||
log_s->last_syn_time = os_jiffies();
|
||||
}
|
||||
|
||||
__log_save_work_end:
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t log_save_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct log_save_s *log_s = (struct log_save_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if (log_s->fp)
|
||||
{
|
||||
osal_ftruncate(log_s->fp);
|
||||
osal_fclose(log_s->fp);
|
||||
}
|
||||
if (log_s)
|
||||
{
|
||||
LOG_FREE(log_s);
|
||||
msi->priv = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&log_s->work, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *creat_log_save_stream(const char *name, uint32_t syn_interval, uint32_t update_file_interval)
|
||||
{
|
||||
struct log_save_s *log_s = (struct log_save_s *) LOG_MALLOC(sizeof(struct log_save_s));
|
||||
struct msi *s = NULL;
|
||||
if (log_s)
|
||||
{
|
||||
memset(log_s, 0, sizeof(struct log_save_s));
|
||||
log_s->syn_interval = syn_interval;
|
||||
log_s->update_file_interval = update_file_interval;
|
||||
s = msi_new(name, 10, NULL);
|
||||
if (s)
|
||||
{
|
||||
s->action = log_save_action;
|
||||
s->priv = (void *) log_s;
|
||||
s->enable = 1;
|
||||
log_s->s = s;
|
||||
OS_WORK_INIT(&log_s->work, log_save_work, 0);
|
||||
os_run_work_delay(&log_s->work, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_FREE(log_s);
|
||||
log_s = NULL;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
32
sdk/app/debug_log_msi/log_save_msi.h
Normal file
32
sdk/app/debug_log_msi/log_save_msi.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef __LOG_SAVE_STREAM_H
|
||||
#define __LOG_SAVE_STREAM_H
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "stream_frame.h"
|
||||
#include "osal_file.h"
|
||||
|
||||
#define CACHE_SIZE (4096)
|
||||
|
||||
struct log_save_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *s;
|
||||
uint32_t save_len;
|
||||
uint8_t save_buf[CACHE_SIZE + 64]; // 设置一个缓冲区,暂时是4K
|
||||
uint16_t offset; // 这个只会小于等于CACHE_SIZE
|
||||
uint16_t start_offset; // 因为写入sd存在可能不对齐的问题,所以这里会有一个基础偏移来作为对齐
|
||||
uint32_t last_syn_time; // 上一次同步的时间
|
||||
uint32_t lastupdate_file_time; // 上一次更换文件的时间
|
||||
uint32_t update_file_interval; // 定时切换log文件,尽量保证旧文件是完整的
|
||||
uint32_t filesize;
|
||||
uint16_t syn_interval; // 同步间隔
|
||||
uint8_t drop_data_flag; // 是否需要写入interrupt drop标志
|
||||
void *fp;
|
||||
};
|
||||
|
||||
void *creat_log_save_stream(const char *name, uint32_t syn_interval, uint32_t update_file_interval);
|
||||
|
||||
#endif
|
||||
822
sdk/app/decode/h264_decode_msi.c
Normal file
822
sdk/app/decode/h264_decode_msi.c
Normal file
@@ -0,0 +1,822 @@
|
||||
#include "basic_include.h"
|
||||
#include "dev.h"
|
||||
#include "dev/jpg/hgjpg.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "devid.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "osal/work.h"
|
||||
#include "stream_frame.h"
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/video/dvp/jpeg/jpg_common.h"
|
||||
#include "osal/event.h"
|
||||
#include "user_work/user_work.h"
|
||||
#include "lib/video/h264/h264_drv.h"
|
||||
#include "dev/h264/hg264.h"
|
||||
#include "lib/scale/scale_common.h"
|
||||
#include "scale/scale_dev.h"
|
||||
|
||||
#ifndef DECODE_MAX_W
|
||||
#define DECODE_MAX_W (320)
|
||||
#endif
|
||||
|
||||
#ifndef DECODE_MAX_H
|
||||
#define DECODE_MAX_H (180)
|
||||
#endif
|
||||
#define DECODE_MAX_SIZE (DECODE_MAX_W * DECODE_MAX_H * 3 / 2)
|
||||
|
||||
#define H264_ROM_MIN_SIZE (100 * 1024 + 4096)
|
||||
|
||||
extern void scale2_from_jpeg_config_for_msi(struct scale_device *scale_dev, uint32_t yinsram, uint32_t uinsram, uint32_t vinsram, uint32_t yuvoutbuf, uint32 in_w, uint32 in_h, uint32 out_w,
|
||||
uint32 out_h, uint8_t larger);
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define MAX_DECODE_NUM (8)
|
||||
|
||||
#ifndef MAX_DECODE_YUV_TX
|
||||
#define MAX_DECODE_YUV_TX (1)
|
||||
#endif
|
||||
|
||||
struct h264_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct fbpool tx_pool;
|
||||
uint8_t *scaler2buf_y;
|
||||
uint8_t *scaler2buf_u;
|
||||
uint8_t *scaler2buf_v;
|
||||
struct h264_device *h264_dev;
|
||||
struct scale_device *scale_dev;
|
||||
uint32_t last_decode_time; // 记录上一次解码的时间,预防有异常的时候可以计算超时
|
||||
uint32_t dec_y_offset;
|
||||
uint32_t dec_uv_offset;
|
||||
uint16_t now_decode_pw;
|
||||
uint16_t scale_p1_w;
|
||||
uint16_t p1_w;
|
||||
uint16_t p1_h;
|
||||
struct framebuff *parent_fb;
|
||||
struct framebuff *current_fb;
|
||||
uint32_t max_data_size;
|
||||
|
||||
struct str_info h264_str;
|
||||
struct h264_header h264_head;
|
||||
struct h264_cfg_t dec_cfg;
|
||||
struct h264_ctl_t dec_ctl;
|
||||
|
||||
uint32_t rom_max_size;
|
||||
uint8_t *rom;
|
||||
uint8_t *ref_mem;
|
||||
uint32_t ref_max_size;
|
||||
|
||||
uint16_t w, h;
|
||||
// 硬件模块是否准备好
|
||||
// 是否自动释放空间(可能会导致碎片化严重,但是可以充分利用空间)
|
||||
uint8_t hardware_ready : 1, auto_free_space : 1, hardware_err : 1, is_register_isr : 1, sps_flag : 1, only_I_H264 : 1, unlock : 1, rev : 1;
|
||||
};
|
||||
|
||||
static void stream_jpg_decode_scale2_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
}
|
||||
|
||||
static void stream_jpg_decode_scale2_ov_isr(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
// struct scale_device *scale_dev = (struct scale_device *)irq_data;
|
||||
}
|
||||
|
||||
static int32_t h264_dec_done(uint32 irq_flags, uint32 irq_data, uint32 param)
|
||||
{
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) irq_data;
|
||||
decode->hardware_ready = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32 h264_decode_work(struct os_work *work)
|
||||
{
|
||||
int ret;
|
||||
uint8_t unlock = 0;
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) work;
|
||||
struct framebuff *fb;
|
||||
// static int count = 0;
|
||||
// 检测解码模块是否完成或者超时代表解码失败
|
||||
// 能进去,模块需要reset或者已经解码完毕,可以重新去解码,否则只能慢慢等超时或者硬件解码完成
|
||||
if (decode->hardware_err || decode->hardware_ready || os_jiffies() - decode->last_decode_time > 1000)
|
||||
{
|
||||
if (decode->current_fb && (os_jiffies() - decode->last_decode_time > 1000))
|
||||
{
|
||||
// 解码可能失败了
|
||||
os_printf(KERN_ERR "decode failed1:%d\n", decode->hardware_ready);
|
||||
os_printf(KERN_ERR "decode->hardware_err:%d\n", decode->hardware_err);
|
||||
|
||||
decode->sps_flag = 0;
|
||||
decode->hardware_ready = 1;
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
// 不再解码了
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
|
||||
// 这里最好将硬件模块停止
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 解码异常
|
||||
else if (decode->hardware_err)
|
||||
{
|
||||
h264_dec_intr_status(decode->h264_dev, &decode->dec_ctl);
|
||||
//-- clear the frm end flag
|
||||
h264_clr_intr(decode->h264_dev);
|
||||
h264_dec_flag_chk(decode->dec_ctl.enc_end_flags);
|
||||
_os_printf(KERN_ERR "decode failed2\n");
|
||||
decode->hardware_err = 0;
|
||||
decode->hardware_ready = 1;
|
||||
if (decode->current_fb)
|
||||
{
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
// 不再解码了
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
}
|
||||
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 解码完成,检查有解码完的数据需要发送
|
||||
else if (decode->current_fb)
|
||||
{
|
||||
h264_dec_intr_status(decode->h264_dev, &decode->dec_ctl);
|
||||
//-- clear the frm end flag
|
||||
h264_clr_intr(decode->h264_dev);
|
||||
h264_dec_flag_chk(decode->dec_ctl.enc_end_flags);
|
||||
// os_printf("%s:%d\tbuf:%X\n",__FUNCTION__,__LINE__,get_stream_real_data(decode->current_fb));
|
||||
fb = decode->current_fb;
|
||||
fb->time = decode->parent_fb->time;
|
||||
fb->mtype = F_YUV;
|
||||
fb->stype = decode->parent_fb->stype;
|
||||
fb->datatag = decode->parent_fb->datatag;
|
||||
fb->srcID = decode->parent_fb->srcID;
|
||||
_os_printf("&");
|
||||
|
||||
msi_output_fb(decode->msi, fb);
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
decode->current_fb = NULL;
|
||||
decode->is_register_isr = 0;
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 硬件可用,但是current_fb不存在
|
||||
// 有两种可能
|
||||
// 一、没有需要解码的图片
|
||||
// 二、有需要解码的图片,但是fb没有申请成功或者内存空间不足以去解码图片数据
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
if (unlock)
|
||||
{
|
||||
scale_mutex_unlock(2, SCALE_LOCK_H264_DECODE1);
|
||||
unlock = 0;
|
||||
decode->unlock = 0;
|
||||
}
|
||||
|
||||
// 这里没有解码的图片,尝试去看看有没有需要解码图片
|
||||
if (!decode->parent_fb)
|
||||
{
|
||||
// 接收图片,尝试看看是否要解码
|
||||
decode->parent_fb = msi_get_fb(decode->msi, 0);
|
||||
|
||||
// 需要解码,然后申请空间
|
||||
if (decode->parent_fb)
|
||||
{
|
||||
goto start_decode;
|
||||
}
|
||||
// 不需要解码
|
||||
else
|
||||
{
|
||||
// 为了腾出空间,释放空间
|
||||
if (decode->auto_free_space)
|
||||
{
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
decode->now_decode_pw = 0;
|
||||
}
|
||||
goto not_decode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto start_decode;
|
||||
}
|
||||
|
||||
// 开始尝试解码
|
||||
start_decode:
|
||||
// 检查是否需要解码(检查绑定msi的模块是否需要接收)
|
||||
{
|
||||
uint32_t send_count = msi_output_fb(decode->msi, NULL);
|
||||
// os_printf("send_count:%X\n",send_count);
|
||||
if (!send_count)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
goto not_decode;
|
||||
}
|
||||
}
|
||||
|
||||
struct framebuff *rfb = decode->parent_fb->next;
|
||||
struct fb_h264_s *h264_priv = (struct fb_h264_s *) rfb->priv;
|
||||
// w变化,就需要等待I帧
|
||||
if (decode->w != h264_priv->w || decode->h != h264_priv->h)
|
||||
{
|
||||
decode->sps_flag = 0;
|
||||
if (decode->ref_mem && (uint32_t) decode->ref_mem != 0x40000000)
|
||||
{
|
||||
uint32_t r_w = ((h264_priv->w + 15) >> 4) << 4;
|
||||
uint32_t r_h = ((h264_priv->h + 15) >> 4) << 4;
|
||||
uint32_t ref_max_size = (r_w * (r_h + 48)) + (r_w * (r_h + 48)) / 2 + 3 * 4096;
|
||||
if (decode->ref_max_size < ref_max_size)
|
||||
{
|
||||
STREAM_FREE(decode->ref_mem);
|
||||
decode->ref_mem = NULL;
|
||||
decode->ref_max_size = 0;
|
||||
decode->w = 0;
|
||||
decode->h = 0;
|
||||
}
|
||||
// 如果空间足够,修改frm_width与frm_height
|
||||
else
|
||||
{
|
||||
decode->w = h264_priv->w;
|
||||
decode->h = h264_priv->h;
|
||||
decode->dec_cfg.frm_width = r_w;
|
||||
decode->dec_cfg.frm_height = r_h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果不是I帧,并且sps_flag没有解析过,就删除编码,等待到I帧
|
||||
if (h264_priv->type != 1 && !decode->sps_flag)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
os_printf("type:%d\n", h264_priv->type);
|
||||
os_printf("sps_flag:%d\n", decode->sps_flag);
|
||||
goto not_decode;
|
||||
}
|
||||
|
||||
// 如果空间不够,那么就重新申请空间
|
||||
if (decode->rom_max_size < rfb->len)
|
||||
{
|
||||
STREAM_FREE(decode->rom);
|
||||
decode->rom = NULL;
|
||||
decode->rom_max_size = 0;
|
||||
}
|
||||
if (!decode->rom)
|
||||
{
|
||||
uint32_t rom_max_size = rfb->len > H264_ROM_MIN_SIZE ? rfb->len : H264_ROM_MIN_SIZE;
|
||||
decode->rom = STREAM_MALLOC(rom_max_size + 4096);
|
||||
if (decode->rom)
|
||||
{
|
||||
decode->rom_max_size = rom_max_size;
|
||||
}
|
||||
}
|
||||
if (h264_priv->type == 1)
|
||||
{
|
||||
if (decode->only_I_H264)
|
||||
{
|
||||
uint32_t w = h264_priv->w;
|
||||
uint32_t h = h264_priv->h;
|
||||
uint32_t r_w = ((w + 15) >> 4) << 4;
|
||||
uint32_t r_h = ((h + 15) >> 4) << 4;
|
||||
|
||||
decode->dec_cfg.frm_width = r_w;
|
||||
decode->dec_cfg.frm_height = r_h;
|
||||
|
||||
decode->w = w;
|
||||
decode->h = h;
|
||||
|
||||
decode->ref_mem = (uint8_t *) 0x40000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!decode->ref_mem)
|
||||
{
|
||||
uint32_t w = h264_priv->w;
|
||||
uint32_t h = h264_priv->h;
|
||||
uint32_t r_w = ((w + 15) >> 4) << 4;
|
||||
uint32_t r_h = ((h + 15) >> 4) << 4;
|
||||
|
||||
decode->ref_mem = STREAM_MALLOC((r_w * (r_h + 48)) + (r_w * (r_h + 48)) / 2 + 3 * 4096);
|
||||
if (decode->ref_mem)
|
||||
{
|
||||
decode->ref_max_size = (r_w * (r_h + 48)) + (r_w * (r_h + 48)) / 2 + 3 * 4096;
|
||||
sys_dcache_clean_range((uint32_t *) decode->ref_mem, decode->ref_max_size);
|
||||
|
||||
decode->dec_cfg.frm_width = r_w;
|
||||
decode->dec_cfg.frm_height = r_h;
|
||||
|
||||
decode->w = w;
|
||||
decode->h = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果是P帧,如果是I帧only就不需要解码P帧
|
||||
else if (h264_priv->type == 2 && decode->only_I_H264)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
goto not_decode;
|
||||
}
|
||||
|
||||
if (!decode->only_I_H264 && !decode->ref_mem)
|
||||
{
|
||||
os_printf("malloc fail ref_mem:%X\n", decode->ref_mem);
|
||||
goto not_decode;
|
||||
}
|
||||
// 申请空间失败
|
||||
if (!decode->rom)
|
||||
{
|
||||
os_printf("malloc fail rom:%X\tref_mem:%X\n", decode->rom, decode->ref_mem);
|
||||
goto not_decode;
|
||||
}
|
||||
|
||||
if (decode->w != h264_priv->w || decode->h != h264_priv->h)
|
||||
{
|
||||
os_printf(KERN_ERR "h264_decode_msi: w[%d] or h[%d] not match dw[%d],dh[%d]\n", h264_priv->w, h264_priv->h, decode->w, decode->h);
|
||||
// 移除,不符合要求,不解码
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
goto not_decode;
|
||||
}
|
||||
// 获取锁
|
||||
ret = scale_mutex_lock(2, SCALE_LOCK_H264_DECODE1, NULL);
|
||||
if (ret)
|
||||
{
|
||||
goto not_decode;
|
||||
}
|
||||
decode->unlock = 1;
|
||||
// 申请到fb,申请解码空间
|
||||
fb = fbpool_get(&decode->tx_pool, 0, decode->msi);
|
||||
if (fb)
|
||||
{
|
||||
// 因为这个是解码的数据,所以默认parent_fb的data是一个参数内容,而不是真实的data,真实jpg的data应该是附在parent_fb后面其他节点
|
||||
struct jpg_decode_arg_s *msg = (struct jpg_decode_arg_s *) decode->parent_fb->data;
|
||||
// 没有找到,代表发送过来的不是jpg或者说对应参数没有配置,不解码
|
||||
if (msg)
|
||||
{
|
||||
// 为fb申请解码空间,申请不到下次申请
|
||||
fb->len = msg->yuv_arg.out_w * msg->yuv_arg.out_h * 3 / 2;
|
||||
if (fb->len <= decode->max_data_size)
|
||||
{
|
||||
struct jpg_decode_arg_s *cfg;
|
||||
cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
memset(cfg, 0, sizeof(struct jpg_decode_arg_s));
|
||||
// 提前配置好data的长度
|
||||
memcpy(fb->priv, msg, sizeof(struct jpg_decode_arg_s));
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_SET_W_H, (uint32_t) fb);
|
||||
|
||||
// fb->type = SET_DATA_TYPE(YUV, GET_DATA_TYPE2(decode->parent_fb->type));
|
||||
|
||||
// msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_SET_STEP, (uint32_t) cfg);
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_READY, (uint32_t) fb);
|
||||
if (!decode->hardware_err)
|
||||
{
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECOE_START, (uint32_t) decode->parent_fb);
|
||||
}
|
||||
|
||||
decode->current_fb = fb;
|
||||
decode->last_decode_time = os_jiffies();
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf(KERN_ERR "config err,max size w:%d\th:%d\tmax_mem:%d\n", DECODE_MAX_W, DECODE_MAX_H, decode->max_data_size);
|
||||
// 不符合,需要删除,不去解码
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("%s:%d\tdecode msg isn't normal\tmsg:%X\tname:%s\n", __FUNCTION__, __LINE__, msg, decode->parent_fb->msi->name);
|
||||
|
||||
// 不符合,需要删除,不去编码
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
not_decode:
|
||||
if (unlock)
|
||||
{
|
||||
scale_mutex_unlock(2, SCALE_LOCK_H264_DECODE1);
|
||||
decode->unlock = 0;
|
||||
}
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
struct framebuff *fb;
|
||||
if (decode->unlock)
|
||||
{
|
||||
scale_mutex_unlock(2, SCALE_LOCK_H264_DECODE1);
|
||||
decode->unlock = 0;
|
||||
}
|
||||
|
||||
if (decode->rom)
|
||||
{
|
||||
STREAM_FREE(decode->rom);
|
||||
decode->rom = NULL;
|
||||
}
|
||||
|
||||
if (decode->ref_mem && (uint32_t) decode->ref_mem != 0x40000000)
|
||||
{
|
||||
STREAM_FREE(decode->ref_mem);
|
||||
decode->ref_mem = NULL;
|
||||
decode->ref_max_size = 0;
|
||||
}
|
||||
// 释放资源fb资源文件,priv是独立申请的
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&decode->tx_pool, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
}
|
||||
|
||||
// 预分配空间释放
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&decode->tx_pool);
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
STREAM_LIBC_FREE(decode);
|
||||
}
|
||||
break;
|
||||
|
||||
// 停止硬件
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&decode->work, 1);
|
||||
// 关闭硬件
|
||||
scale_close(decode->scale_dev);
|
||||
|
||||
if (decode->current_fb)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
}
|
||||
if (decode->parent_fb)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
fbpool_put(&decode->tx_pool, fb);
|
||||
// 不需要内核去释放fb
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_DECODE:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_DECODE_SET_W_H:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
struct jpg_decode_arg_s *cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) msi->priv;
|
||||
decode->p1_w = cfg->yuv_arg.out_w;
|
||||
decode->p1_h = cfg->yuv_arg.out_h;
|
||||
decode->scale_p1_w = ((decode->p1_w + 3) / 4) * 4;
|
||||
if (cfg->rotate)
|
||||
{
|
||||
decode->dec_y_offset = decode->p1_w * (decode->p1_h - 1);
|
||||
decode->dec_uv_offset = ((decode->scale_p1_w / 2 + 3) / 4) * 4 * (decode->p1_h / 2 - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->dec_y_offset = 0;
|
||||
decode->dec_uv_offset = 0;
|
||||
}
|
||||
|
||||
cfg->yuv_arg.y_off = decode->dec_y_offset;
|
||||
cfg->yuv_arg.uv_off = decode->dec_uv_offset;
|
||||
cfg->yuv_arg.y_size = decode->scale_p1_w * decode->p1_h;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_SET_IN_OUT_SIZE:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_SET_STEP:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_READY:
|
||||
{
|
||||
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) msi->priv;
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
uint32 dst = (uint32_t) fb->data;
|
||||
struct jpg_decode_arg_s *cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
uint8_t err = 0;
|
||||
|
||||
#if 0
|
||||
h264_request_irq(decode->h264_dev, H264_FRAME_DONE, h264_dec_done, (uint32) decode);
|
||||
#else
|
||||
// 如果空间不够,就重新申请把
|
||||
if (decode->p1_w > decode->now_decode_pw)
|
||||
{
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
uint8_t scale_coeff = 0;
|
||||
uint32_t iw = cfg->decode_w;
|
||||
// uint32_t ih = cfg->decode_h;
|
||||
uint32_t ow = decode->p1_w;
|
||||
// uint32_t oh = decode->p1_h;
|
||||
if(iw >= ow)
|
||||
{
|
||||
scale_coeff = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale_coeff = 2;
|
||||
}
|
||||
|
||||
// 默认一定申请到,没有做申请失败的处理
|
||||
decode->scaler2buf_y = STREAM_LIBC_MALLOC(0x20+ow+scale_coeff*20*SRAMBUF_WLEN*4+256);
|
||||
decode->scaler2buf_u = STREAM_LIBC_MALLOC(((0x12+ow/2+scale_coeff*11*SRAMBUF_WLEN*2+128 + 3)/4)*4);
|
||||
decode->scaler2buf_v = STREAM_LIBC_MALLOC(((0x12+ow/2+scale_coeff*11*SRAMBUF_WLEN*2+128 + 3)/4)*4);
|
||||
if (!decode->scaler2buf_y || !decode->scaler2buf_u || !decode->scaler2buf_v)
|
||||
{
|
||||
os_printf(KERN_ERR "%s:%d err\tpw:%X\tnow_pw:%X\n", __FUNCTION__, __LINE__, decode->p1_w, decode->now_decode_pw);
|
||||
os_printf(KERN_ERR "fail y:%X\tu:%X\tv:%X\n", decode->scaler2buf_y, decode->scaler2buf_u, decode->scaler2buf_v);
|
||||
decode->now_decode_pw = 0;
|
||||
err = 1;
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->now_decode_pw = decode->p1_w;
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
{
|
||||
|
||||
scale2_from_h264_config_for_msi(decode->scale_dev, (uint32_t) decode->scaler2buf_y, (uint32_t) decode->scaler2buf_u, (uint32_t) decode->scaler2buf_v, dst, cfg->decode_w,
|
||||
cfg->decode_h, cfg->yuv_arg.out_w, cfg->yuv_arg.out_h, 10);
|
||||
|
||||
if (!decode->is_register_isr)
|
||||
{
|
||||
scale_request_irq(decode->scale_dev, FRAME_END, (scale_irq_hdl) &stream_jpg_decode_scale2_done, (uint32) decode);
|
||||
scale_request_irq(decode->scale_dev, INBUF_OV, (scale_irq_hdl) &stream_jpg_decode_scale2_ov_isr, (uint32) decode);
|
||||
h264_request_irq(decode->h264_dev, H264_FRAME_DONE, h264_dec_done, (uint32) decode);
|
||||
// decode->is_register_isr = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->hardware_err = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECOE_START:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
struct framebuff *rfb = fb->next;
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) msi->priv;
|
||||
struct fb_h264_s *h264_priv = (struct fb_h264_s *) rfb->priv;
|
||||
uint32_t dst = (uint32_t) rfb->data;
|
||||
uint32_t dst_len = rfb->len;
|
||||
uint8_t *rom_ptr = (uint8_t *) (((uint32_t) decode->rom + 0xfff) & (~0xfff));
|
||||
|
||||
decode->hardware_ready = 0;
|
||||
decode->last_decode_time = os_jiffies();
|
||||
// 这里开启对应的h264解码
|
||||
// 如果是I帧,就去处理sps和pps
|
||||
if (h264_priv->type == 1 && !decode->sps_flag)
|
||||
{
|
||||
sps_setting(&decode->h264_str, &decode->h264_head, decode->w, decode->h);
|
||||
cfg_setting(decode->h264_dev, &decode->h264_head, &decode->dec_cfg, &decode->dec_ctl);
|
||||
h264_dec_refbuf_set(decode->h264_dev, ((uint32_t) decode->ref_mem + 0xfff) & (~0xfff), (struct h264_cfg_t *) &decode->dec_cfg, (struct h264_ctl_t *) &decode->dec_ctl);
|
||||
pps_setting(&decode->h264_str, &decode->h264_head, h264_priv->pps, h264_priv->pps_len);
|
||||
decode->sps_flag = 1;
|
||||
}
|
||||
h264_rom_memcpy(rom_ptr, (uint8_t *) dst, dst_len);
|
||||
h264_decode_I_P_setting(&decode->h264_str, &decode->h264_head, rom_ptr);
|
||||
|
||||
if (h264_priv->type == 1)
|
||||
{
|
||||
decode->dec_ctl.frm_type = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->dec_ctl.frm_type = 0;
|
||||
}
|
||||
|
||||
h264_dec_src_room_set(decode->h264_dev, ((uint32_t) decode->ref_mem + 0xfff) & (~0xfff), (struct h264_cfg_t *) &decode->dec_cfg, (struct h264_ctl_t *) &decode->dec_ctl);
|
||||
h264_dec_a_frame(decode->h264_dev, dst_len + 4, &decode->dec_ctl, &decode->h264_head, &decode->h264_str, (uint32_t) rom_ptr);
|
||||
h264_decode_start(decode->h264_dev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
if (fb->mtype != F_JPG_DECODE_MSG)
|
||||
{
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
// 解码是要先获取jpg,然后申请解码后size的空间,然后启动解码
|
||||
// 不再支持传入msi的name(因为硬件解码模块只有一个,所以不支持这个msi的名称命名)
|
||||
struct msi *h264_decode_msi(const char *name, uint8_t only_I_H264)
|
||||
{
|
||||
(void) name; // 不再支持修改名字
|
||||
uint8_t is_new;
|
||||
struct msi *msi = msi_new(name, MAX_DECODE_NUM, &is_new);
|
||||
struct h264_msi_s *decode = (struct h264_msi_s *) msi->priv;
|
||||
if (is_new)
|
||||
{
|
||||
decode = (struct h264_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct h264_msi_s));
|
||||
decode->msi = msi;
|
||||
msi->priv = (void *) decode;
|
||||
msi->action = decode_msi_action;
|
||||
|
||||
uint32_t init_count = 0;
|
||||
void *priv;
|
||||
fbpool_init(&decode->tx_pool, 2);
|
||||
while (init_count < 2)
|
||||
{
|
||||
uint8_t *data = (uint8_t *) STREAM_MALLOC(DECODE_MAX_SIZE);
|
||||
ASSERT(data);
|
||||
sys_dcache_invalid_range((uint32_t *) data, DECODE_MAX_SIZE);
|
||||
priv = (void *) STREAM_LIBC_ZALLOC(sizeof(struct jpg_decode_arg_s));
|
||||
FBPOOL_SET_INFO(&decode->tx_pool, init_count, data, 0, priv);
|
||||
init_count++;
|
||||
}
|
||||
|
||||
decode->h264_dev = (struct h264_device *) dev_get(HG_H264_DEVID);
|
||||
decode->scale_dev = (struct scale_device *) dev_get(HG_SCALE2_DEVID);
|
||||
decode->scaler2buf_y = NULL;
|
||||
decode->scaler2buf_u = NULL;
|
||||
decode->scaler2buf_v = NULL;
|
||||
decode->now_decode_pw = 0;
|
||||
decode->hardware_ready = 1;
|
||||
decode->auto_free_space = 1;
|
||||
decode->only_I_H264 = only_I_H264;
|
||||
// decode->w = w;
|
||||
// decode->h = h;
|
||||
decode->max_data_size = DECODE_MAX_SIZE;
|
||||
// decode->rom = os_malloc_psram(100 * 1024 + 4096);
|
||||
// decode->ref_mem = os_malloc_psram((w * (h + 48)) + (w * (h + 48)) / 2 + 3 * 4096);
|
||||
// sys_dcache_clean_range((uint32_t *) decode->ref_mem, (w * (h + 48)) + (w * (h + 48)) / 2 + 3 * 4096);
|
||||
|
||||
decode->dec_cfg.enc_mode = 0;
|
||||
// decode->dec_cfg.frm_width = w;
|
||||
// decode->dec_cfg.frm_height = h;
|
||||
msi->enable = 1;
|
||||
OS_WORK_INIT(&decode->work, h264_decode_work, 0);
|
||||
os_run_work_delay(&decode->work, 1);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
344
sdk/app/decode/jpg_decode_msg_msi.c
Normal file
344
sdk/app/decode/jpg_decode_msg_msi.c
Normal file
@@ -0,0 +1,344 @@
|
||||
/*******************************************************************************************************
|
||||
* 该文件主要是为了给jpeg配置需要解码的信息,然后传递给到硬件解码
|
||||
******************************************************************************************************/
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "stream_frame.h"
|
||||
#include "utlist.h"
|
||||
#include "osal/task.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/work.h"
|
||||
#include "osal_file.h"
|
||||
#include "jpgdef.h"
|
||||
#include "utlist.h"
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "stream_define.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "user_work/user_work.h"
|
||||
|
||||
// 获取jpeg的w和h,没有做太多容错,所以尽量给的是正确的jpeg,否则可能异常
|
||||
#define GET_16(p) (((p)[0] << 8) | (p)[1])
|
||||
|
||||
static int parse_SOF(uint8_t *d, uint32_t *w, uint32_t *h)
|
||||
{
|
||||
if (d[0] != 8)
|
||||
{
|
||||
printf("Invalid precision %d in SOF0\n", d[0]);
|
||||
return -1;
|
||||
}
|
||||
*h = GET_16(d + 1);
|
||||
*w = GET_16(d + 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_jpg(uint8_t *jpg_buf, uint32_t maxsize, uint32_t *w, uint32_t *h)
|
||||
{
|
||||
uint8_t *buf = jpg_buf;
|
||||
uint8_t EOI_flag = 0;
|
||||
uint32_t i = 0;
|
||||
int res = 1;
|
||||
int blen = 0;
|
||||
for (i = 0; i < maxsize; i += blen + 2)
|
||||
{
|
||||
if (buf[i] != 0xFF)
|
||||
{
|
||||
printf("Found %02X at %d, expecting FF\n", buf[i], i);
|
||||
goto parse_jpg_end;
|
||||
}
|
||||
while (buf[i + 1] == 0xFF)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
if (buf[i + 1] == 0xD8)
|
||||
{
|
||||
blen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
blen = GET_16(buf + i + 2);
|
||||
}
|
||||
|
||||
switch (buf[i + 1])
|
||||
{
|
||||
case 0xDB: /* Quantization Table */
|
||||
break;
|
||||
case 0xC0: /* Start of Frame */
|
||||
parse_SOF(buf + i + 4, w, h);
|
||||
res = 0;
|
||||
// printf("w:%d\th:%d\n",*w,*h);
|
||||
break;
|
||||
case 0xC4: /* Huffman Table */
|
||||
|
||||
break;
|
||||
case 0xDD: /* DRI */
|
||||
break;
|
||||
case 0xDA: /* Start of Scan */
|
||||
goto parse_jpg_end;
|
||||
}
|
||||
}
|
||||
|
||||
parse_jpg_end:
|
||||
|
||||
if (!res)
|
||||
{
|
||||
for (i = maxsize - 1; i >= maxsize - 16; i--)
|
||||
{
|
||||
if (buf[i] != 0xFF)
|
||||
{
|
||||
// os_printf("EOI Found %02X at %d, expecting FF\n", buf[i], i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((i < maxsize - 1) && (buf[i + 1] == 0xD9))
|
||||
{
|
||||
EOI_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((!res) && (!EOI_flag))
|
||||
{
|
||||
res = 1;
|
||||
os_printf("EOI No found FF D9\n");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int ex_parse_jpg(uint8_t *jpg_buf, uint32_t maxsize, uint32_t *w, uint32_t *h)
|
||||
{
|
||||
return parse_jpg(jpg_buf, maxsize, w, h);
|
||||
}
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
struct jpg_decode_msg_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct framebuff *rfb;
|
||||
uint32_t magic; // 会赋值到对应参数,用于后续msi的识别,如果为0,就是没有任何处理
|
||||
uint16_t out_w;
|
||||
uint16_t out_h;
|
||||
uint16_t step_w;
|
||||
uint16_t step_h;
|
||||
uint16_t x, y; // 解码配置的x和y,如果没有可以不配置
|
||||
uint16_t force_type; // 强转类型(统一将解码的类型修改,不按照filter,0是无效)
|
||||
uint8_t filter; // 过滤解码的类型
|
||||
uint8_t ish264;
|
||||
};
|
||||
|
||||
static int32 jpg_decode_msg_work(struct os_work *work)
|
||||
{
|
||||
struct jpg_decode_msg_s *decode_msg = (struct jpg_decode_msg_s *) work;
|
||||
struct framebuff *rfb;
|
||||
struct framebuff *fb;
|
||||
int res;
|
||||
if (decode_msg->rfb)
|
||||
{
|
||||
rfb = decode_msg->rfb;
|
||||
// 这里可以考虑用自己的内存管理,后续看情况修改接口
|
||||
fb = fb_alloc(NULL, sizeof(struct jpg_decode_arg_s), 0, decode_msg->msi);
|
||||
// 申请不到就等下次进来再去尝试解码吧
|
||||
if (fb)
|
||||
{
|
||||
fb_ref(fb, rfb);
|
||||
fb->datatag = rfb->datatag;
|
||||
fb->stype = rfb->stype;
|
||||
fb->srcID = rfb->srcID;
|
||||
struct jpg_decode_arg_s *msg = (struct jpg_decode_arg_s *) fb->data;
|
||||
struct yuv_arg_s *yuv_msg = &msg->yuv_arg;
|
||||
memset(msg, 0, sizeof(struct jpg_decode_arg_s));
|
||||
yuv_msg->out_w = decode_msg->out_w;
|
||||
yuv_msg->out_h = decode_msg->out_h;
|
||||
yuv_msg->x = decode_msg->x;
|
||||
yuv_msg->y = decode_msg->y;
|
||||
yuv_msg->magic = decode_msg->magic;
|
||||
yuv_msg->dispcnt = fb->datatag;
|
||||
// os_printf("yuv_msg->dispcnt:%d\n",yuv_msg->dispcnt);
|
||||
msg->step_w = decode_msg->step_w;
|
||||
msg->step_h = decode_msg->step_h;
|
||||
|
||||
if (rfb->mtype == F_H264)
|
||||
{
|
||||
struct fb_h264_s *h264_priv = (struct fb_h264_s *) rfb->priv;
|
||||
res = 0;
|
||||
msg->decode_w = h264_priv->w;
|
||||
msg->decode_h = h264_priv->h;
|
||||
}
|
||||
else if (rfb->mtype == F_JPG)
|
||||
{
|
||||
res = parse_jpg(rfb->data, rfb->len, &msg->decode_w, &msg->decode_h);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = 1;
|
||||
}
|
||||
if (!res)
|
||||
{
|
||||
fb->mtype = F_JPG_DECODE_MSG;
|
||||
fb->stype = decode_msg->force_type ? decode_msg->force_type : rfb->stype;
|
||||
fb->time = rfb->time;
|
||||
msi_output_fb(decode_msg->msi, fb);
|
||||
msi_delete_fb(NULL, rfb);
|
||||
decode_msg->rfb = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
msi_delete_fb(NULL, fb);
|
||||
msi_delete_fb(NULL, rfb);
|
||||
decode_msg->rfb = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decode_msg->rfb = msi_get_fb(decode_msg->msi, 0);
|
||||
}
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t decode_msg_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct jpg_decode_msg_s *decode_msg = (struct jpg_decode_msg_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
|
||||
// 这里msi已经被删除,那么就要考虑tx_pool的资源释放了
|
||||
// 能进来这里,就是代表所有fb都已经用完了
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&decode_msg->work, 1);
|
||||
STREAM_LIBC_FREE(decode_msg);
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&decode_msg->work, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_DECODE_JPEG_MSG:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_JPEG_DECODE_X_Y:
|
||||
{
|
||||
decode_msg->x = arg >> 16;
|
||||
decode_msg->y = arg & 0xffff;
|
||||
}
|
||||
break;
|
||||
|
||||
// 配置强转类型
|
||||
case MSI_JPEG_DECODE_FORCE_TYPE:
|
||||
{
|
||||
decode_msg->force_type = arg;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_JPEG_DECODE_MAGIC:
|
||||
{
|
||||
decode_msg->magic = arg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
|
||||
if (decode_msg->ish264)
|
||||
{
|
||||
if (fb->mtype != F_H264)
|
||||
{
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fb->mtype != F_JPG)
|
||||
{
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
if (decode_msg->filter && !(decode_msg->filter == fb->stype))
|
||||
{
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *jpg_decode_msg_msi(const char *name, uint16_t out_w, uint16_t out_h, uint16_t step_w, uint16_t step_h, uint32_t filter)
|
||||
{
|
||||
struct msi *msi = msi_new(name, 8, NULL);
|
||||
struct jpg_decode_msg_s *decode_msg = (struct jpg_decode_msg_s *) msi->priv;
|
||||
if (!decode_msg)
|
||||
{
|
||||
decode_msg = (struct jpg_decode_msg_s *) STREAM_LIBC_ZALLOC(sizeof(struct jpg_decode_msg_s));
|
||||
msi->priv = (void *) decode_msg;
|
||||
msi->action = decode_msg_msi_action;
|
||||
decode_msg->msi = msi;
|
||||
decode_msg->out_w = out_w;
|
||||
decode_msg->out_h = out_h;
|
||||
decode_msg->step_w = step_w;
|
||||
decode_msg->step_h = step_h;
|
||||
decode_msg->filter = filter;
|
||||
decode_msg->rfb = NULL;
|
||||
decode_msg->ish264 = 0;
|
||||
msi->enable = 1;
|
||||
// 启动workqueue
|
||||
OS_WORK_INIT(&decode_msg->work, jpg_decode_msg_work, 0);
|
||||
os_run_work_delay(&decode_msg->work, 1);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
|
||||
struct msi *h264_decode_msg_msi(const char *name, uint16_t out_w, uint16_t out_h, uint16_t step_w, uint16_t step_h, uint32_t filter)
|
||||
{
|
||||
struct msi *msi = msi_new(name, 8, NULL);
|
||||
struct jpg_decode_msg_s *decode_msg = (struct jpg_decode_msg_s *) msi->priv;
|
||||
if (!decode_msg)
|
||||
{
|
||||
decode_msg = (struct jpg_decode_msg_s *) STREAM_LIBC_ZALLOC(sizeof(struct jpg_decode_msg_s));
|
||||
msi->priv = (void *) decode_msg;
|
||||
msi->action = decode_msg_msi_action;
|
||||
decode_msg->msi = msi;
|
||||
decode_msg->out_w = out_w;
|
||||
decode_msg->out_h = out_h;
|
||||
decode_msg->step_w = step_w;
|
||||
decode_msg->step_h = step_h;
|
||||
decode_msg->filter = filter;
|
||||
decode_msg->rfb = NULL;
|
||||
decode_msg->ish264 = 0;
|
||||
decode_msg->ish264 = 1;
|
||||
msi->enable = 1;
|
||||
// 启动workqueue
|
||||
OS_WORK_INIT(&decode_msg->work, jpg_decode_msg_work, 0);
|
||||
os_run_work_delay(&decode_msg->work, 1);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
616
sdk/app/decode/jpg_decode_msi.c
Normal file
616
sdk/app/decode/jpg_decode_msi.c
Normal file
@@ -0,0 +1,616 @@
|
||||
#include "basic_include.h"
|
||||
#include "dev.h"
|
||||
#include "dev/jpg/hgjpg.h"
|
||||
#include "dev/scale/hgscale.h"
|
||||
#include "devid.h"
|
||||
#include "lib/lcd/lcd.h"
|
||||
#include "osal/work.h"
|
||||
#include "stream_frame.h"
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/video/dvp/jpeg/jpg_common.h"
|
||||
#include "osal/event.h"
|
||||
#include "user_work/user_work.h"
|
||||
|
||||
#ifndef DECODE_MAX_W
|
||||
#define DECODE_MAX_W (320)
|
||||
#endif
|
||||
|
||||
#ifndef DECODE_MAX_H
|
||||
#define DECODE_MAX_H (180)
|
||||
#endif
|
||||
#define DECODE_MAX_SIZE (DECODE_MAX_W * DECODE_MAX_H * 3 / 2)
|
||||
|
||||
extern void scale2_from_jpeg_config_for_msi(struct scale_device *scale_dev, uint32_t yinsram, uint32_t uinsram, uint32_t vinsram, uint32_t yuvoutbuf, uint32 in_w, uint32 in_h, uint32 out_w,
|
||||
uint32 out_h, uint8_t larger);
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define MAX_DECODE_NUM (8)
|
||||
|
||||
#ifndef MAX_DECODE_YUV_TX
|
||||
#define MAX_DECODE_YUV_TX (1)
|
||||
#endif
|
||||
|
||||
struct jpg_msi_s
|
||||
{
|
||||
struct os_work work;
|
||||
struct msi *msi;
|
||||
struct fbpool tx_pool;
|
||||
uint8_t *scaler2buf_y;
|
||||
uint8_t *scaler2buf_u;
|
||||
uint8_t *scaler2buf_v;
|
||||
struct jpg_device *jpg_dev;
|
||||
struct scale_device *scale_dev;
|
||||
uint32_t last_decode_time; // 记录上一次解码的时间,预防有异常的时候可以计算超时
|
||||
uint32_t dec_y_offset;
|
||||
uint32_t dec_uv_offset;
|
||||
uint16_t now_decode_pw;
|
||||
uint16_t scale_p1_w;
|
||||
uint16_t p1_w;
|
||||
uint16_t p1_h;
|
||||
struct framebuff *parent_fb;
|
||||
struct framebuff *current_fb;
|
||||
|
||||
uint32_t max_data_size;
|
||||
|
||||
// 硬件模块是否准备好
|
||||
uint8_t hardware_ready;
|
||||
uint8_t hardware_err;
|
||||
uint8_t is_register_isr;
|
||||
// 是否自动释放空间(可能会导致碎片化严重,但是可以充分利用空间)
|
||||
uint8_t auto_free_space;
|
||||
};
|
||||
|
||||
static void stream_jpg_decode_scale2_done(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
}
|
||||
|
||||
static void stream_jpg_decode_scale2_ov_isr(uint32 irq_flag, uint32 irq_data, uint32 param1)
|
||||
{
|
||||
// struct scale_device *scale_dev = (struct scale_device *)irq_data;
|
||||
os_printf("sor2");
|
||||
}
|
||||
|
||||
static void stream_jpg_decode_done(uint32 irq_flag, uint32 irq_data, uint32 param1, uint32 param2)
|
||||
{
|
||||
_os_printf("*");
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) irq_data;
|
||||
decode->hardware_ready = 1;
|
||||
}
|
||||
|
||||
// 这里解码失败,暂时代表硬件完成,后面应该有错误标志位,主要为了解码失败移除当前frame
|
||||
static void stream_jpg_decode_err(uint32 irq_flag, uint32 irq_data, uint32 param1, uint32 param2)
|
||||
{
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) irq_data;
|
||||
os_printf("decode err\r\n");
|
||||
// decode->hardware_ready = 1;
|
||||
decode->hardware_err = 1;
|
||||
}
|
||||
|
||||
static int32 jpg_decode_work(struct os_work *work)
|
||||
{
|
||||
|
||||
int ret;
|
||||
uint8_t unlock = 0;
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) work;
|
||||
struct framebuff *fb;
|
||||
// static int count = 0;
|
||||
// 检测解码模块是否完成或者超时代表解码失败
|
||||
// 能进去,模块需要reset或者已经解码完毕,可以重新去解码,否则只能慢慢等超时或者硬件解码完成
|
||||
if (decode->hardware_err || decode->hardware_ready || os_jiffies() - decode->last_decode_time > 1000)
|
||||
{
|
||||
if (decode->current_fb && (os_jiffies() - decode->last_decode_time > 1000))
|
||||
{
|
||||
// 解码可能失败了
|
||||
os_printf(KERN_ERR"decode failed1:%d\n", decode->hardware_ready);
|
||||
os_printf(KERN_ERR"decode->hardware_err:%d\n", decode->hardware_err);
|
||||
decode->hardware_ready = 1;
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
// 不再解码了
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
|
||||
// 这里最好将硬件模块停止
|
||||
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 解码异常
|
||||
else if (decode->hardware_err)
|
||||
{
|
||||
_os_printf(KERN_ERR"decode failed2\n");
|
||||
decode->hardware_err = 0;
|
||||
decode->hardware_ready = 1;
|
||||
if (decode->current_fb)
|
||||
{
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
// 不再解码了
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
}
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 解码完成,检查有解码完的数据需要发送
|
||||
else if (decode->current_fb)
|
||||
{
|
||||
// os_printf("%s:%d\tbuf:%X\n",__FUNCTION__,__LINE__,get_stream_real_data(decode->current_fb));
|
||||
fb = decode->current_fb;
|
||||
fb->time = decode->parent_fb->time;
|
||||
fb->mtype = F_YUV;
|
||||
fb->stype = decode->parent_fb->stype;
|
||||
fb->datatag = decode->parent_fb->datatag;
|
||||
fb->srcID = decode->parent_fb->srcID;
|
||||
_os_printf("&");
|
||||
|
||||
msi_output_fb(decode->msi, fb);
|
||||
// 无论是完成还是失败,都要释放这张图片了
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
decode->current_fb = NULL;
|
||||
decode->is_register_isr = 0;
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
// 硬件可用,但是current_fb不存在
|
||||
// 有两种可能
|
||||
// 一、没有需要解码的图片
|
||||
// 二、有需要解码的图片,但是fb没有申请成功或者内存空间不足以去解码图片数据
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
if (unlock)
|
||||
{
|
||||
jpg_close(decode->jpg_dev);
|
||||
jpg_mutex_unlock(JPGID1, JPG_LOCK_DECODE);
|
||||
unlock = 0;
|
||||
}
|
||||
|
||||
// 这里没有解码的图片,尝试去看看有没有需要解码图片
|
||||
if (!decode->parent_fb)
|
||||
{
|
||||
// 接收图片,尝试看看是否要解码
|
||||
decode->parent_fb = msi_get_fb(decode->msi, 0);
|
||||
|
||||
// 需要解码,然后申请空间
|
||||
if (decode->parent_fb)
|
||||
{
|
||||
// os_printf("parent_fb:%X\n",decode->parent_fb);
|
||||
goto start_decode;
|
||||
}
|
||||
// 不需要解码
|
||||
else
|
||||
{
|
||||
// 为了腾出空间,释放空间
|
||||
if (decode->auto_free_space)
|
||||
{
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
decode->now_decode_pw = 0;
|
||||
}
|
||||
goto not_decode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto start_decode;
|
||||
}
|
||||
|
||||
// 开始尝试解码
|
||||
start_decode:
|
||||
// 检查是否需要解码(检查绑定msi的模块是否需要接收)
|
||||
{
|
||||
uint32_t send_count = msi_output_fb(decode->msi, NULL);
|
||||
if (!send_count)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
goto not_decode;
|
||||
}
|
||||
}
|
||||
// 先去申请jpg1的锁,确保只有一个模块在使用jpg1
|
||||
ret = jpg_mutex_lock(JPGID1, JPG_LOCK_DECODE, NULL);
|
||||
if (ret)
|
||||
{
|
||||
goto not_decode;
|
||||
}
|
||||
// jpg_open(decode->jpg_dev);
|
||||
// 申请到fb,申请解码空间
|
||||
fb = fbpool_get(&decode->tx_pool, 0, decode->msi);
|
||||
if (fb)
|
||||
{
|
||||
// 因为这个是解码的数据,所以默认parent_fb的data是一个参数内容,而不是真实的data,真实jpg的data应该是附在parent_fb后面其他节点
|
||||
struct jpg_decode_arg_s *msg = (struct jpg_decode_arg_s *) decode->parent_fb->data;
|
||||
// 没有找到,代表发送过来的不是jpg或者说对应参数没有配置,不解码
|
||||
if (msg)
|
||||
{
|
||||
// 为fb申请解码空间,申请不到下次申请
|
||||
fb->len = msg->yuv_arg.out_w * msg->yuv_arg.out_h * 3 / 2;
|
||||
if (fb->len <= decode->max_data_size)
|
||||
{
|
||||
struct jpg_decode_arg_s *cfg;
|
||||
cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
memset(cfg, 0, sizeof(struct jpg_decode_arg_s));
|
||||
// 提前配置好data的长度
|
||||
memcpy(fb->priv, msg, sizeof(struct jpg_decode_arg_s));
|
||||
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_SET_W_H, (uint32_t) fb);
|
||||
|
||||
// fb->type = SET_DATA_TYPE(YUV, GET_DATA_TYPE2(decode->parent_fb->type));
|
||||
|
||||
// msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_SET_STEP, (uint32_t) cfg);
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECODE_READY, (uint32_t) fb);
|
||||
if (!decode->hardware_err)
|
||||
{
|
||||
msi_do_cmd(decode->msi, MSI_CMD_DECODE, MSI_DECOE_START, (uint32_t) decode->parent_fb);
|
||||
}
|
||||
|
||||
decode->current_fb = fb;
|
||||
decode->last_decode_time = os_jiffies();
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf(KERN_ERR"config err,max size w:%d\th:%d\tmax_mem:%d\n",DECODE_MAX_W,DECODE_MAX_H,decode->max_data_size);
|
||||
// 不符合,需要删除,不去编码
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("%s:%d\tdecode msg isn't normal\tmsg:%X\tname:%s\n", __FUNCTION__, __LINE__, msg, decode->parent_fb->msi->name);
|
||||
|
||||
// 不符合,需要删除,不去编码
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
|
||||
msi_delete_fb(NULL, fb);
|
||||
fb = NULL;
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 解锁
|
||||
unlock = 1;
|
||||
}
|
||||
}
|
||||
not_decode:
|
||||
if (unlock)
|
||||
{
|
||||
jpg_mutex_unlock(JPGID1, JPG_LOCK_DECODE);
|
||||
}
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_msi_action(struct msi *msi, uint32 cmd_id, uint32 param1, uint32 param2)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) msi->priv;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
struct framebuff *fb;
|
||||
// 释放资源fb资源文件,priv是独立申请的
|
||||
while (1)
|
||||
{
|
||||
fb = fbpool_get(&decode->tx_pool, 0, NULL);
|
||||
if (!fb)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// 预分配空间释放
|
||||
if (fb->priv)
|
||||
{
|
||||
STREAM_LIBC_FREE(fb->priv);
|
||||
}
|
||||
|
||||
// 预分配空间释放
|
||||
if (fb->data)
|
||||
{
|
||||
STREAM_FREE(fb->data);
|
||||
fb->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&decode->tx_pool);
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
jpg_close(decode->jpg_dev);
|
||||
STREAM_LIBC_FREE(decode);
|
||||
jpg_mutex_unlock(JPGID1, JPG_LOCK_DECODE);
|
||||
}
|
||||
break;
|
||||
|
||||
// 停止硬件
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
os_work_cancle2(&decode->work, 1);
|
||||
// 关闭硬件
|
||||
scale_close(decode->scale_dev);
|
||||
jpg_close(decode->jpg_dev);
|
||||
|
||||
if (decode->current_fb)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->current_fb);
|
||||
decode->current_fb = NULL;
|
||||
}
|
||||
if (decode->parent_fb)
|
||||
{
|
||||
msi_delete_fb(NULL, decode->parent_fb);
|
||||
decode->parent_fb = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
fbpool_put(&decode->tx_pool, fb);
|
||||
// 不需要内核去释放fb
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_DECODE:
|
||||
{
|
||||
uint32_t cmd_self = (uint32_t) param1;
|
||||
uint32_t arg = param2;
|
||||
switch (cmd_self)
|
||||
{
|
||||
case MSI_DECODE_SET_W_H:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
struct jpg_decode_arg_s *cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) msi->priv;
|
||||
decode->p1_w = cfg->yuv_arg.out_w;
|
||||
decode->p1_h = cfg->yuv_arg.out_h;
|
||||
decode->scale_p1_w = ((decode->p1_w + 3) / 4) * 4;
|
||||
if (cfg->rotate)
|
||||
{
|
||||
decode->dec_y_offset = decode->p1_w * (decode->p1_h - 1);
|
||||
decode->dec_uv_offset = ((decode->scale_p1_w / 2 + 3) / 4) * 4 * (decode->p1_h / 2 - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->dec_y_offset = 0;
|
||||
decode->dec_uv_offset = 0;
|
||||
}
|
||||
|
||||
cfg->yuv_arg.y_off = decode->dec_y_offset;
|
||||
cfg->yuv_arg.uv_off = decode->dec_uv_offset;
|
||||
cfg->yuv_arg.y_size = decode->scale_p1_w * decode->p1_h;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_SET_IN_OUT_SIZE:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_SET_STEP:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECODE_READY:
|
||||
{
|
||||
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) msi->priv;
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
uint32 dst = (uint32_t) fb->data;
|
||||
struct jpg_decode_arg_s *cfg = (struct jpg_decode_arg_s *) fb->priv;
|
||||
uint8_t err = 0;
|
||||
// 如果空间不够,就重新申请把
|
||||
if (decode->p1_w > decode->now_decode_pw)
|
||||
{
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
// 默认一定申请到,没有做申请失败的处理
|
||||
decode->scaler2buf_y = STREAM_LIBC_MALLOC(0x20 + decode->p1_w + 17 * 4 * SRAMBUF_WLEN);
|
||||
decode->scaler2buf_u = STREAM_LIBC_MALLOC(0x12 + decode->p1_w / 2 + 9 * 4 * SRAMBUF_WLEN);
|
||||
decode->scaler2buf_v = STREAM_LIBC_MALLOC(0x12 + decode->p1_w / 2 + 9 * 4 * SRAMBUF_WLEN);
|
||||
if (!decode->scaler2buf_y || !decode->scaler2buf_u || !decode->scaler2buf_v)
|
||||
{
|
||||
os_printf(KERN_ERR "%s:%d err\tpw:%X\tnow_pw:%X\n", __FUNCTION__, __LINE__, decode->p1_w, decode->now_decode_pw);
|
||||
os_printf(KERN_ERR "fail y:%X\tu:%X\tv:%X\n", decode->scaler2buf_y, decode->scaler2buf_u, decode->scaler2buf_v);
|
||||
decode->now_decode_pw = 0;
|
||||
err = 1;
|
||||
if (decode->scaler2buf_y)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_y);
|
||||
decode->scaler2buf_y = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_u)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_u);
|
||||
decode->scaler2buf_u = NULL;
|
||||
}
|
||||
|
||||
if (decode->scaler2buf_v)
|
||||
{
|
||||
STREAM_LIBC_FREE(decode->scaler2buf_v);
|
||||
decode->scaler2buf_v = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->now_decode_pw = decode->p1_w;
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
{
|
||||
//jpg_open(decode->jpg_dev);
|
||||
scale2_from_jpeg_config_for_msi(decode->scale_dev, (uint32_t)decode->scaler2buf_y, (uint32_t)decode->scaler2buf_u, (uint32_t)decode->scaler2buf_v, dst, cfg->decode_w, cfg->decode_h, cfg->yuv_arg.out_w,
|
||||
cfg->yuv_arg.out_h, 10);
|
||||
|
||||
if (!decode->is_register_isr)
|
||||
{
|
||||
scale_request_irq(decode->scale_dev, FRAME_END, (scale_irq_hdl) &stream_jpg_decode_scale2_done, (uint32) decode);
|
||||
scale_request_irq(decode->scale_dev, INBUF_OV, (scale_irq_hdl) &stream_jpg_decode_scale2_ov_isr, (uint32) decode);
|
||||
jpg_request_irq(decode->jpg_dev, (jpg_irq_hdl) &stream_jpg_decode_done, JPG_IRQ_FLAG_JPG_DONE, (void *) decode);
|
||||
jpg_request_irq(decode->jpg_dev, (jpg_irq_hdl) &stream_jpg_decode_err, JPG_IRQ_FLAG_ERROR, (void *) decode);
|
||||
// decode->is_register_isr = 1;
|
||||
}
|
||||
jpg_decode_target(decode->jpg_dev, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
decode->hardware_err = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_DECOE_START:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) arg;
|
||||
struct framebuff *rfb = fb->next;
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) msi->priv;
|
||||
uint32_t dst = (uint32_t) rfb->data;
|
||||
decode->hardware_ready = 0;
|
||||
decode->last_decode_time = os_jiffies();
|
||||
// scale_open(decode->scale_dev);
|
||||
sys_dcache_clean_range((uint32_t*)dst,rfb->len);
|
||||
jpg_decode_photo(decode->jpg_dev, dst, rfb->len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
if (fb->mtype != F_JPG_DECODE_MSG)
|
||||
{
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
// 解码是要先获取jpg,然后申请解码后size的空间,然后启动解码
|
||||
// 不再支持传入msi的name(因为硬件解码模块只有一个,所以不支持这个msi的名称命名)
|
||||
struct msi *jpg_decode_msi(const char *name)
|
||||
{
|
||||
(void) name; // 不再支持修改名字
|
||||
uint8_t is_new;
|
||||
struct msi *msi = msi_new(S_JPG_DECODE, MAX_DECODE_NUM, &is_new);
|
||||
struct jpg_msi_s *decode = (struct jpg_msi_s *) msi->priv;
|
||||
if (is_new)
|
||||
{
|
||||
decode = (struct jpg_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct jpg_msi_s));
|
||||
decode->msi = msi;
|
||||
msi->priv = (void *) decode;
|
||||
msi->action = decode_msi_action;
|
||||
|
||||
uint32_t init_count = 0;
|
||||
void *priv;
|
||||
fbpool_init(&decode->tx_pool, MAX_DECODE_YUV_TX);
|
||||
while (init_count < MAX_DECODE_YUV_TX)
|
||||
{
|
||||
uint8_t *data = (uint8_t *) STREAM_MALLOC(DECODE_MAX_SIZE);
|
||||
ASSERT(data);
|
||||
sys_dcache_invalid_range((uint32_t*)data, DECODE_MAX_SIZE);
|
||||
priv = (void *) STREAM_LIBC_ZALLOC(sizeof(struct jpg_decode_arg_s));
|
||||
FBPOOL_SET_INFO(&decode->tx_pool, init_count, data, 0, priv);
|
||||
init_count++;
|
||||
}
|
||||
|
||||
decode->jpg_dev = (struct jpg_device *) dev_get(HG_JPG1_DEVID);
|
||||
decode->scale_dev = (struct scale_device *) dev_get(HG_SCALE2_DEVID);
|
||||
decode->scaler2buf_y = NULL;
|
||||
decode->scaler2buf_u = NULL;
|
||||
decode->scaler2buf_v = NULL;
|
||||
decode->now_decode_pw = 0;
|
||||
decode->hardware_ready = 1;
|
||||
decode->auto_free_space = 1;
|
||||
decode->max_data_size = DECODE_MAX_SIZE;
|
||||
|
||||
msi->enable = 1;
|
||||
OS_WORK_INIT(&decode->work, jpg_decode_work, 0);
|
||||
os_run_work_delay(&decode->work, 1);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
54
sdk/app/decode/route_msi.c
Normal file
54
sdk/app/decode/route_msi.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/***********************************************************************
|
||||
* 这个文件仅仅是中转数据,主要为了一些硬件模块是插入才有数据,所以外部希望
|
||||
* 绑定的时候,可能硬件没有准备好,所以创建一个中转msi,硬件准备好就发送到
|
||||
* 中转msi,然后中转msi帮忙转发出去,外部调用就是用中转msi帮定就可以了,
|
||||
* 这样硬件准备好会自动通过中转msi去转发
|
||||
***********************************************************************/
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
static int32_t route_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
switch (cmd_id)
|
||||
{
|
||||
// 帮忙转发,但是永远不需要放在队列中
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *)param1;
|
||||
fb_get(fb);
|
||||
msi_output_fb(msi, fb);
|
||||
ret = RET_OK + 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
// 中转(路由)msi,不需要接收,仅仅发送就可以了
|
||||
struct msi *route_msi(const char *name)
|
||||
{
|
||||
// 设置1个接收,只是为了可以output_fb给到这个msi
|
||||
struct msi *msi = msi_new(name, 0, NULL);
|
||||
if (msi)
|
||||
{
|
||||
msi->action = route_msi_action;
|
||||
msi->enable = 1;
|
||||
}
|
||||
return msi;
|
||||
}
|
||||
150
sdk/app/dns_eloop/dns_eloop.c
Normal file
150
sdk/app/dns_eloop/dns_eloop.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file dns_eloop.c
|
||||
* @author HUGE-IC Application Team
|
||||
* @version V1.0.0
|
||||
* @date 2021-07-16
|
||||
* @brief a simple dns server
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2021 HUGE-IC</center></h2>
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "osal/task.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/sleep.h"
|
||||
#include "lib/common/sysevt.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "netif/ethernetif.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/init.h"
|
||||
#include "lwip/prot/dns.h"
|
||||
//#include "lib/net/dns/dns.h"
|
||||
#include "dns_eloop.h"
|
||||
#include "event.h"
|
||||
|
||||
|
||||
#define dns_dbg(fmt, ...) os_printf(fmt, ##__VA_ARGS__)
|
||||
#define dns_err(fmt, ...) os_printf(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DNS_RECVBUF_SIZE (512)
|
||||
|
||||
struct dns_mgr {
|
||||
struct netif *netif;
|
||||
int32 sock;
|
||||
uint8 recvbuf[DNS_RECVBUF_SIZE];
|
||||
uint8 stop: 1;
|
||||
};
|
||||
|
||||
static struct dns_mgr *dns;
|
||||
|
||||
static void dns_query_refuse(struct sockaddr_in *addr, uint8 *data, uint32 len)
|
||||
{
|
||||
struct dns_hdr *hdr = (struct dns_hdr *)data;
|
||||
// 置起flags中response,并且返回query失败原因, 我们并未实现dns功能,只是拒绝了查询
|
||||
hdr->flags1 |= DNS_FLAG1_RESPONSE;
|
||||
hdr->flags2 &= ~DNS_FLAG2_ERR_MASK;
|
||||
hdr->flags2 |= 5; // 5: Refused - 服务器拒绝执行请求操作
|
||||
sendto(dns->sock, data, len, 0, (const struct sockaddr *)addr, sizeof(struct sockaddr));
|
||||
//dns_dbg("dns query refused - %s:%d\r\n", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
}
|
||||
|
||||
static void dns_task_eloop(void *ei, void *d)
|
||||
{
|
||||
int32 ret = 0;
|
||||
socklen_t len = 16; // 接收socket地址需要用
|
||||
struct sockaddr_in addr;
|
||||
struct dns_hdr *hdr;
|
||||
|
||||
ret = recvfrom(dns->sock, dns->recvbuf, DNS_RECVBUF_SIZE, 0, (struct sockaddr *)&addr, &len);
|
||||
// 最少dns_hdr长度12
|
||||
if (ret >= 12 && !dns->stop) {
|
||||
hdr = (struct dns_hdr *)dns->recvbuf;
|
||||
// 最少dns_hdr + dns_query = 12 + 4
|
||||
if (hdr->numquestions > 0 && ret >= (12 + 4)) {
|
||||
dns_query_refuse(&addr, dns->recvbuf, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__init static int32 _dns_start(char *ifname)
|
||||
{
|
||||
int32 ret = -1;
|
||||
int32 sock = -1;
|
||||
int32 optval = 1;
|
||||
struct sockaddr_in local_addr;
|
||||
struct ifreq nif;
|
||||
|
||||
dns = os_zalloc(sizeof(struct dns_mgr));
|
||||
if(dns == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
dns->netif = netif_find(ifname);
|
||||
if (dns->netif == NULL) {
|
||||
dns_err("netif:%s is not exist\r\n", ifname);
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == -1) {
|
||||
dns_err("create socket failed\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
fcntl(sock, F_SETFL, O_NONBLOCK);
|
||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
|
||||
os_strncpy(nif.ifr_name, dns->netif->name, 2);
|
||||
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &nif, sizeof(nif));
|
||||
os_memset(&local_addr, 0, sizeof(local_addr));
|
||||
local_addr.sin_family = AF_INET;
|
||||
local_addr.sin_port = htons(53);
|
||||
local_addr.sin_addr.s_addr = dns->netif->ip_addr.addr;
|
||||
ret = bind(sock, (struct sockaddr *)&local_addr, sizeof(struct sockaddr));
|
||||
if (ret == -1) {
|
||||
dns_err("bind fail\r\n");
|
||||
closesocket(sock);
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
dns->sock = sock;
|
||||
dns_dbg("dns sock :%x\r\n", (uint32)sock);
|
||||
eloop_add_fd(dns->sock, EVENT_READ, EVENT_F_ENABLED, dns_task_eloop, NULL);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32 dns_start_eloop(char *ifname)
|
||||
{
|
||||
int32 ret = 0;
|
||||
|
||||
if (ifname == NULL) {
|
||||
dns_err("invalid param!\r\n");
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
if (dns) {
|
||||
dns->stop = 0;
|
||||
dns_err("dns already running ...\r\n");
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
ret = _dns_start(ifname);
|
||||
ASSERT(!ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dns_stop_eloop(char *ifname)
|
||||
{
|
||||
if(dns){
|
||||
dns->stop = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
8
sdk/app/dns_eloop/dns_eloop.h
Normal file
8
sdk/app/dns_eloop/dns_eloop.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef _DNS_ELOOP_H_
|
||||
#define _DNS_ELOOP_H_
|
||||
|
||||
int32 dns_start_eloop(char *ifname);
|
||||
void dns_stop_eloop(char *ifname);
|
||||
|
||||
#endif
|
||||
|
||||
622
sdk/app/ffavimuxer/avimuxer.c
Normal file
622
sdk/app/ffavimuxer/avimuxer.c
Normal file
@@ -0,0 +1,622 @@
|
||||
#include "avimuxer.h"
|
||||
#include "basic_include.h"
|
||||
#include "fatfs/osal_file.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "stream_define.h"
|
||||
|
||||
const uint8_t avi_zero = 0;
|
||||
#define CONTENT_MAX_SIZE (512 * 1024 * 1024)
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0 /* set file offset to offset */
|
||||
#endif
|
||||
#ifndef SEEK_CUR
|
||||
#define SEEK_CUR 1 /* set file offset to current plus offset */
|
||||
#endif
|
||||
#ifndef SEEK_END
|
||||
#define SEEK_END 2 /* set file offset to EOF plus offset */
|
||||
#endif
|
||||
|
||||
|
||||
static uint32_t avi_tell(F_FILE *fp)
|
||||
{
|
||||
return osal_ftell(fp);
|
||||
}
|
||||
|
||||
static void pre_avi_seek(F_FILE *fp, uint32_t offset)
|
||||
{
|
||||
uint32_t filesize = osal_fsize(fp);
|
||||
if(filesize != offset)
|
||||
{
|
||||
osal_fseek(fp, offset);
|
||||
osal_ftruncate(fp);
|
||||
_os_printf("avi size: %d\n", osal_fsize(fp));
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t avi_seek(F_FILE *fp, int32_t offset, int seek_mode)
|
||||
{
|
||||
uint32_t fp_offset = 0;
|
||||
uint32_t filesize = osal_fsize(fp);
|
||||
if (seek_mode == SEEK_SET)
|
||||
{
|
||||
fp_offset = offset;
|
||||
}
|
||||
else if (seek_mode == SEEK_CUR)
|
||||
{
|
||||
fp_offset = osal_ftell(fp) + offset;
|
||||
}
|
||||
else if (seek_mode == SEEK_END)
|
||||
{
|
||||
fp_offset = osal_fsize(fp) + offset;
|
||||
}
|
||||
osal_fseek(fp, fp_offset);
|
||||
if (filesize < fp_offset)
|
||||
{
|
||||
osal_ftruncate(fp);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
static uint32_t avi_write(void *buf, uint32_t size, uint32_t n, F_FILE *fp)
|
||||
{
|
||||
// 返回值0是代表异常
|
||||
uint32_t ret = 1;
|
||||
uint32_t write_size_total = size * n;
|
||||
ret = osal_fwrite(buf, 1, write_size_total, fp);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
static F_FILE *avi_open(const char *filename, char *mode)
|
||||
{
|
||||
return osal_fopen(filename, mode);
|
||||
}
|
||||
|
||||
static void avi_close(F_FILE *fp)
|
||||
{
|
||||
osal_fclose(fp);
|
||||
}
|
||||
|
||||
static void avi_truncate(F_FILE *fp, uint32_t offset)
|
||||
{
|
||||
avi_seek(fp, offset, SEEK_CUR); // 预留的的空间
|
||||
osal_ftruncate(fp);
|
||||
}
|
||||
|
||||
|
||||
static void avi_file_syn(F_FILE *fp)
|
||||
{
|
||||
osal_fsync(fp);
|
||||
}
|
||||
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC os_malloc
|
||||
#define STREAM_LIBC_FREE os_free
|
||||
#define STREAM_LIBC_ZALLOC os_zalloc
|
||||
|
||||
|
||||
#define AVIF_HASINDEX (1 << 4)
|
||||
#define AVIF_ISINTERLEAVED (1 << 8)
|
||||
#define AVIIF_KEYFRAME (1 << 4)
|
||||
|
||||
#define AVI_AUDIO_FRAME (0 << 31)
|
||||
#define AVI_VIDEO_FRAME (1 << 31)
|
||||
#define AVI_KEY_FRAME (1 << 30)
|
||||
#define AVI_INSERT_FRAME (1 << 29)
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, member) ((size_t) &((type *) 0)->member)
|
||||
#endif
|
||||
|
||||
#define AVI_LIST_EMP (512)
|
||||
#define IDX_MAX_SIZE (1024*1024)
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct
|
||||
{
|
||||
uint32_t microsec_per_frame;
|
||||
uint32_t maxbytes_per_Sec;
|
||||
uint32_t padding_granularity;
|
||||
uint32_t flags;
|
||||
uint32_t total_frames;
|
||||
uint32_t initial_frames;
|
||||
uint32_t number_streams;
|
||||
uint32_t suggested_bufsize;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t reserved[4];
|
||||
} AVI_HEADER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char fcc_type[4];
|
||||
char fcc_codec[4];
|
||||
uint32_t flags;
|
||||
uint16_t priority;
|
||||
uint16_t language;
|
||||
uint32_t initial_frames;
|
||||
uint32_t scale;
|
||||
uint32_t rate;
|
||||
uint32_t start;
|
||||
uint32_t length;
|
||||
uint32_t suggested_bufsize;
|
||||
uint32_t quality;
|
||||
uint32_t sample_size;
|
||||
uint16_t vrect_left;
|
||||
uint16_t vrect_top;
|
||||
uint16_t vrect_right;
|
||||
uint16_t vrect_bottom;
|
||||
|
||||
} STREAM_HEADER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t format_tag;
|
||||
uint16_t channels;
|
||||
uint32_t sample_per_sec;
|
||||
uint32_t avgbyte_per_sec;
|
||||
uint16_t block_align;
|
||||
uint16_t bits_per_sample;
|
||||
uint16_t size;
|
||||
} WAVE_FORMAT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t size;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint16_t planes;
|
||||
uint16_t bitcount;
|
||||
uint32_t compression;
|
||||
uint32_t image_size;
|
||||
uint32_t xpels_per_meter;
|
||||
uint32_t ypels_per_meter;
|
||||
uint32_t color_used;
|
||||
uint32_t color_important;
|
||||
} BITMAP_FORMAT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t *framesize_lst;
|
||||
uint32_t framesize_fix;
|
||||
uint32_t framesize_idx;
|
||||
uint32_t framesize_max;
|
||||
uint32_t movi_addr;
|
||||
uint32_t movi_addr_end;
|
||||
uint32_t cur_addr;
|
||||
uint32_t frame_base_addr;
|
||||
uint32_t max_size;
|
||||
uint32_t curpos;
|
||||
|
||||
uint32_t now_idx;
|
||||
uint32_t cache_idx;
|
||||
uint32_t total_idx;
|
||||
uint32_t frame_list[AVI_LIST_EMP / 4];
|
||||
|
||||
uint32_t tmp_idx_offset;
|
||||
uint8_t tmp_idx_data[AVI_LIST_EMP / 4 * 16];
|
||||
F_FILE *fp;
|
||||
uint32_t extern_fp;
|
||||
|
||||
char riff[4];
|
||||
uint32_t riff_size;
|
||||
char type_avi[4];
|
||||
|
||||
char hlist[4];
|
||||
uint32_t hlist_size;
|
||||
char type_hdrl[4];
|
||||
|
||||
char avih[4];
|
||||
uint32_t avih_size;
|
||||
AVI_HEADER avi_header;
|
||||
#if 1
|
||||
char slist1[4];
|
||||
uint32_t slist1_size;
|
||||
char type_str1[4];
|
||||
|
||||
char strhdr1[4];
|
||||
uint32_t strhdr1_size;
|
||||
STREAM_HEADER strhdr_audio;
|
||||
|
||||
char strfmt1[4];
|
||||
uint32_t strfmt1_size;
|
||||
WAVE_FORMAT strfmt_audio;
|
||||
#endif
|
||||
|
||||
char slist2[4];
|
||||
uint32_t slist2_size;
|
||||
char type_str2[4];
|
||||
|
||||
char strhdr2[4];
|
||||
uint32_t strhdr2_size;
|
||||
STREAM_HEADER strhdr_video;
|
||||
|
||||
char strfmt2[4];
|
||||
uint32_t strfmt2_size;
|
||||
BITMAP_FORMAT strfmt_video;
|
||||
|
||||
char mlist[4];
|
||||
uint32_t mlist_size;
|
||||
char type_movi[4];
|
||||
|
||||
} AVI_FILE;
|
||||
#pragma pack()
|
||||
|
||||
static uint32_t avi_write_idx_tmp(void *buf, uint32_t size, uint32_t n, AVI_FILE *avi)
|
||||
{
|
||||
// 返回值0是代表异常
|
||||
uint32_t ret = 0;
|
||||
uint32_t write_size_total = size * n;
|
||||
os_memcpy(avi->tmp_idx_data + avi->tmp_idx_offset, buf, write_size_total);
|
||||
avi->tmp_idx_offset += write_size_total;
|
||||
return !ret;
|
||||
}
|
||||
|
||||
static uint32_t avi_write_idx_syn(AVI_FILE *avi)
|
||||
{
|
||||
// 返回值0是代表异常
|
||||
uint32_t ret = avi_write(avi->tmp_idx_data, 1, avi->tmp_idx_offset, avi->fp);
|
||||
avi->tmp_idx_offset = 0;
|
||||
return !ret;
|
||||
}
|
||||
|
||||
void *avimuxer_init2(void *fp, uint32_t max_size, int w, int h, int frate, int gop, int h265, int sampnum)
|
||||
{
|
||||
int samprate = 8000, channels = 1, sampbits = 16;
|
||||
AVI_FILE *avi = STREAM_ZALLOC(1 * sizeof(AVI_FILE));
|
||||
if (!avi)
|
||||
{
|
||||
goto failed;
|
||||
}
|
||||
avi->extern_fp = 1;
|
||||
avi->fp = (F_FILE *) fp;
|
||||
if (!avi->fp)
|
||||
{
|
||||
goto failed;
|
||||
}
|
||||
|
||||
//预先分配空间
|
||||
pre_avi_seek(avi->fp, max_size);
|
||||
|
||||
//开始写入数据头
|
||||
avi_seek(avi->fp, 0, SEEK_SET);
|
||||
|
||||
|
||||
memcpy(avi->avih, "avih", 4);
|
||||
avi->avih_size = sizeof(AVI_HEADER);
|
||||
avi->avi_header.microsec_per_frame = 1000000 / frate;
|
||||
avi->avi_header.maxbytes_per_Sec = w * h * 3;
|
||||
avi->avi_header.flags = AVIF_ISINTERLEAVED | AVIF_HASINDEX;
|
||||
avi->avi_header.number_streams = 1;
|
||||
avi->avi_header.width = w;
|
||||
avi->avi_header.height = h;
|
||||
avi->avi_header.suggested_bufsize = w * h * 3;
|
||||
#if 1
|
||||
memcpy(avi->strhdr1, "strh", 4);
|
||||
memcpy(avi->strhdr_audio.fcc_type, "auds", 4);
|
||||
memcpy(avi->strhdr_audio.fcc_codec, "PCM ", 4);
|
||||
avi->strhdr1_size = sizeof(STREAM_HEADER);
|
||||
avi->strhdr_audio.scale = 1;
|
||||
avi->strhdr_audio.rate = samprate;
|
||||
avi->strhdr_audio.suggested_bufsize = samprate * channels * sampbits / 8;
|
||||
avi->strhdr_audio.sample_size = channels * sampbits / 8;
|
||||
|
||||
memcpy(avi->strfmt1, "strf", 4);
|
||||
avi->strfmt1_size = sizeof(WAVE_FORMAT);
|
||||
avi->strfmt_audio.format_tag = 1;
|
||||
avi->strfmt_audio.channels = channels;
|
||||
avi->strfmt_audio.sample_per_sec = samprate;
|
||||
avi->strfmt_audio.avgbyte_per_sec = samprate * channels * sampbits / 8;
|
||||
avi->strfmt_audio.block_align = channels * sampbits / 8;
|
||||
avi->strfmt_audio.bits_per_sample = sampbits;
|
||||
|
||||
memcpy(avi->slist1, "LIST", 4);
|
||||
memcpy(avi->type_str1, "strl", 4);
|
||||
avi->slist1_size = offsetof(AVI_FILE, slist2) - offsetof(AVI_FILE, type_str1);
|
||||
#endif
|
||||
|
||||
memcpy(avi->strhdr2, "strh", 4);
|
||||
memcpy(avi->strhdr_video.fcc_type, "vids", 4);
|
||||
memcpy(avi->strhdr_video.fcc_codec, h265 ? "MJPG" : "MJPG", 4);
|
||||
avi->strhdr2_size = sizeof(STREAM_HEADER);
|
||||
avi->strhdr_video.scale = 1;
|
||||
avi->strhdr_video.rate = frate;
|
||||
avi->strhdr_video.suggested_bufsize = 0;
|
||||
avi->strhdr_video.quality = -1;
|
||||
avi->strhdr_video.vrect_right = w;
|
||||
avi->strhdr_video.vrect_bottom = h;
|
||||
|
||||
memcpy(avi->strfmt2, "strf", 4);
|
||||
avi->strfmt2_size = sizeof(BITMAP_FORMAT);
|
||||
avi->strfmt_video.size = 40;
|
||||
avi->strfmt_video.width = w;
|
||||
avi->strfmt_video.height = h;
|
||||
avi->strfmt_video.planes = 1;
|
||||
avi->strfmt_video.bitcount = 24;
|
||||
avi->strfmt_video.compression = h265 ? (('H' << 0) | ('E' << 8) | ('V' << 16) | ('1' << 24)) : (('M' << 0) | ('J' << 8) | ('P' << 16) | ('G' << 24));
|
||||
avi->strfmt_video.image_size = w * h * 3;
|
||||
|
||||
memcpy(avi->slist2, "LIST", 4);
|
||||
memcpy(avi->type_str2, "strl", 4);
|
||||
avi->slist2_size = 4 + 4 + 4 + avi->strhdr2_size + 4 + 4 + avi->strfmt2_size;
|
||||
|
||||
memcpy(avi->riff, "RIFF", 4);
|
||||
memcpy(avi->type_avi, "AVI ", 4);
|
||||
memcpy(avi->hlist, "LIST", 4);
|
||||
memcpy(avi->type_hdrl, "hdrl", 4);
|
||||
memcpy(avi->mlist, "LIST", 4);
|
||||
memcpy(avi->type_movi, "movi", 4);
|
||||
avi->hlist_size = sizeof(AVI_FILE) - 12 - offsetof(AVI_FILE, type_hdrl);
|
||||
|
||||
avi_write(&avi->riff, sizeof(AVI_FILE) - offsetof(AVI_FILE, riff), 1, avi->fp);
|
||||
|
||||
// 预分配文件空间
|
||||
uint32_t movi_addr = avi_tell(avi->fp);
|
||||
avi->movi_addr = movi_addr;
|
||||
|
||||
avi->max_size = max_size - movi_addr - 8 - IDX_MAX_SIZE;
|
||||
|
||||
avi->movi_addr_end = movi_addr + avi->max_size;
|
||||
avi->frame_base_addr = avi->movi_addr_end;
|
||||
avi->cur_addr = movi_addr;
|
||||
return avi;
|
||||
|
||||
failed:
|
||||
if (avi)
|
||||
{
|
||||
STREAM_FREE(avi);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void avimuxer_fix_data2(AVI_FILE *avi, int writeidx)
|
||||
{
|
||||
// 只有缓冲区的时候才需要回写
|
||||
if (avi->cache_idx)
|
||||
{
|
||||
uint32_t data, movisize;
|
||||
avi->avi_header.total_frames = avi->strhdr_video.length;
|
||||
|
||||
data = avi->avi_header.total_frames;
|
||||
avi_seek(avi->fp, offsetof(AVI_FILE, avi_header.total_frames) - offsetof(AVI_FILE, riff), SEEK_SET);
|
||||
avi_write(&data, 4, 1, avi->fp);
|
||||
|
||||
#if 1
|
||||
data = avi->strhdr_audio.length;
|
||||
avi_seek(avi->fp, offsetof(AVI_FILE, strhdr_audio.length) - offsetof(AVI_FILE, riff), SEEK_SET);
|
||||
avi_write(&data, 4, 1, avi->fp);
|
||||
#endif
|
||||
|
||||
data = avi->strhdr_video.length;
|
||||
avi_seek(avi->fp, offsetof(AVI_FILE, strhdr_video.length) - offsetof(AVI_FILE, riff), SEEK_SET);
|
||||
avi_write(&data, 4, 1, avi->fp);
|
||||
|
||||
movisize = avi->max_size + 4;
|
||||
avi_seek(avi->fp, offsetof(AVI_FILE, mlist_size) - offsetof(AVI_FILE, riff), SEEK_SET);
|
||||
avi_write(&movisize, 4, 1, avi->fp);
|
||||
|
||||
data = avi->max_size + sizeof(AVI_FILE) - offsetof(AVI_FILE, riff) + avi->total_idx * 16;
|
||||
avi_seek(avi->fp, offsetof(AVI_FILE, riff_size) - offsetof(AVI_FILE, riff), SEEK_SET);
|
||||
avi_write(&data, 4, 1, avi->fp);
|
||||
|
||||
if (writeidx)
|
||||
{
|
||||
|
||||
// 如果相等,需要写入idx1的头
|
||||
avi_seek(avi->fp, avi->frame_base_addr, SEEK_SET);
|
||||
if (avi->movi_addr_end == avi_tell(avi->fp))
|
||||
{
|
||||
uint32_t idx1size;
|
||||
avi_write("idx1", 4, 1, avi->fp);
|
||||
idx1size = avi->total_idx * sizeof(uint32_t) * 4;
|
||||
avi_write(&idx1size, 4, 1, avi->fp);
|
||||
avi->curpos = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t idx1size;
|
||||
uint32_t seek_tmp = avi_tell(avi->fp);
|
||||
idx1size = avi->total_idx * sizeof(uint32_t) * 4;
|
||||
avi_seek(avi->fp, avi->movi_addr_end+4, SEEK_SET);
|
||||
avi_write(&idx1size, 4, 1, avi->fp);
|
||||
avi_seek(avi->fp, seek_tmp, SEEK_SET);
|
||||
}
|
||||
while (avi->now_idx < avi->cache_idx)
|
||||
{
|
||||
avi_write_idx_tmp((avi->frame_list[avi->now_idx] & AVI_VIDEO_FRAME) ? "01dc" : "00wb", 4, 1, avi);
|
||||
data = (avi->frame_list[avi->now_idx] & AVI_KEY_FRAME) ? AVIIF_KEYFRAME : 0;
|
||||
avi_write_idx_tmp(&data, 4, 1, avi);
|
||||
data = avi->curpos;
|
||||
avi_write_idx_tmp(&data, 4, 1, avi);
|
||||
data = avi->frame_list ? avi->frame_list[avi->now_idx] & 0x0fffffff : 0;
|
||||
avi_write_idx_tmp(&data, 4, 1, avi);
|
||||
// 如果是补帧,则不需要增加偏移?
|
||||
if (avi->frame_list[avi->now_idx] & AVI_INSERT_FRAME)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
avi->curpos += data + 8;
|
||||
}
|
||||
|
||||
avi->now_idx++;
|
||||
}
|
||||
|
||||
// 一次性写入索引
|
||||
avi_write_idx_syn(avi);
|
||||
// 记录当前的位置
|
||||
avi->frame_base_addr = avi_tell(avi->fp);
|
||||
|
||||
//如果有空闲,需要添加junk
|
||||
if(osal_fsize(avi->fp) > avi->frame_base_addr+8)
|
||||
{
|
||||
uint32_t remain = osal_fsize(avi->fp) - avi->frame_base_addr - 8;
|
||||
avi_write("JUNK", 4, 1, avi->fp);
|
||||
avi_write(&remain, 4, 1, avi->fp);
|
||||
}
|
||||
else if(osal_fsize(avi->fp) > avi->frame_base_addr)
|
||||
{
|
||||
avi_write("JUNK", 4, 1, avi->fp);
|
||||
}
|
||||
|
||||
avi->now_idx = 0;
|
||||
avi->cache_idx = 0;
|
||||
}
|
||||
avi_file_syn(avi->fp);
|
||||
}
|
||||
}
|
||||
|
||||
void avimuxer_sync(void *ctx)
|
||||
{
|
||||
AVI_FILE *avi = (AVI_FILE *) ctx;
|
||||
if (avi && avi->fp)
|
||||
{
|
||||
avi_file_syn(avi->fp);
|
||||
avimuxer_fix_data2(avi, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void avimuxer_exit2(void *ctx)
|
||||
{
|
||||
AVI_FILE *avi = (AVI_FILE *) ctx;
|
||||
if (avi)
|
||||
{
|
||||
os_printf("avi->extern_fp:%d\n", avi->extern_fp);
|
||||
if (avi->fp)
|
||||
{
|
||||
avimuxer_fix_data2(avi, 1);
|
||||
if (!avi->extern_fp)
|
||||
{
|
||||
avi_close(avi->fp);
|
||||
}
|
||||
}
|
||||
if (avi->framesize_lst)
|
||||
{
|
||||
STREAM_FREE(avi->framesize_lst);
|
||||
}
|
||||
|
||||
STREAM_FREE(avi);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t avimuxer_video2(void *ctx, unsigned char *buf, int len, int key, unsigned pts, uint8_t insert)
|
||||
{
|
||||
uint32_t ret = AVIMUXER_OK;
|
||||
AVI_FILE *avi = (AVI_FILE *) ctx;
|
||||
if (avi == NULL)
|
||||
{
|
||||
ret = AVIMUXER_ERR;
|
||||
goto avimuxer_video2_end;
|
||||
}
|
||||
if (avi->fp)
|
||||
{
|
||||
int alignlen = (len & 1) ? len + 1 : len;
|
||||
// 补帧,不需要写入数据
|
||||
if (!insert)
|
||||
{
|
||||
avi_seek(avi->fp, avi->cur_addr, SEEK_SET);
|
||||
if (avi_tell(avi->fp) - avi->movi_addr + alignlen > avi->movi_addr_end)
|
||||
{
|
||||
ret = AVIMUXER_FULL;
|
||||
goto avimuxer_video2_end;
|
||||
}
|
||||
|
||||
avi_write("01dc", 4, 1, avi->fp);
|
||||
avi_write(&alignlen, 4, 1, avi->fp);
|
||||
avi_write(buf, len, 1, avi->fp);
|
||||
if (len & 1)
|
||||
{
|
||||
avi_write((void *) &avi_zero, 1, 1, avi->fp);
|
||||
}
|
||||
avi->cur_addr = avi_tell(avi->fp);
|
||||
if (avi->movi_addr_end - avi_tell(avi->fp) + 4 > 8)
|
||||
{
|
||||
// 补junk的数据
|
||||
avi_write("JUNK", 4, 1, avi->fp);
|
||||
// 补junk长度
|
||||
uint32_t junklen = avi->movi_addr_end - avi_tell(avi->fp) - 8 + 4;
|
||||
avi_write(&junklen, 4, 1, avi->fp);
|
||||
}
|
||||
}
|
||||
if (avi->cache_idx < sizeof(avi->frame_list) / 4)
|
||||
{
|
||||
if (insert)
|
||||
{
|
||||
avi->frame_list[avi->cache_idx++] = alignlen | AVI_VIDEO_FRAME | AVI_INSERT_FRAME | (key << 30);
|
||||
}
|
||||
else
|
||||
{
|
||||
avi->frame_list[avi->cache_idx++] = alignlen | AVI_VIDEO_FRAME | (key << 30);
|
||||
}
|
||||
|
||||
avi->total_idx++;
|
||||
}
|
||||
avi->strhdr_video.length++;
|
||||
}
|
||||
|
||||
// 同步一次
|
||||
if (avi->cache_idx == sizeof(avi->frame_list) / 4)
|
||||
{
|
||||
avimuxer_fix_data2(avi, 1);
|
||||
avi->cache_idx = 0;
|
||||
avi->cache_idx = 0;
|
||||
}
|
||||
avimuxer_video2_end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t avimuxer_audio2(void *ctx, unsigned char *buf, int len, int key, unsigned pts)
|
||||
{
|
||||
uint32_t ret = AVIMUXER_OK;
|
||||
AVI_FILE *avi = (AVI_FILE *) ctx;
|
||||
if (avi && avi->fp)
|
||||
{
|
||||
int alignlen = (len & 1) ? len + 1 : len;
|
||||
avi_seek(avi->fp, avi->cur_addr, SEEK_SET);
|
||||
if (avi_tell(avi->fp) - avi->movi_addr + alignlen > avi->movi_addr_end)
|
||||
{
|
||||
ret = AVIMUXER_FULL;
|
||||
goto avimuxer_audio2_end;
|
||||
}
|
||||
avi_write("00wb", 4, 1, avi->fp);
|
||||
avi_write(&alignlen, 4, 1, avi->fp);
|
||||
avi_write(buf, len, 1, avi->fp);
|
||||
if (len & 1)
|
||||
{
|
||||
avi_write((void *) &avi_zero, 1, 1, avi->fp);
|
||||
}
|
||||
|
||||
avi->cur_addr = avi_tell(avi->fp);
|
||||
if (avi->movi_addr_end - avi_tell(avi->fp) + 4 > 8)
|
||||
{
|
||||
// 补junk的数据
|
||||
avi_write("JUNK", 4, 1, avi->fp);
|
||||
// 补junk长度
|
||||
uint32_t junklen = avi->movi_addr_end - avi_tell(avi->fp) - 8 + 4;
|
||||
avi_write(&junklen, 4, 1, avi->fp);
|
||||
}
|
||||
|
||||
if (avi->cache_idx < sizeof(avi->frame_list) / 4)
|
||||
{
|
||||
avi->frame_list[avi->cache_idx++] = alignlen | AVI_AUDIO_FRAME;
|
||||
avi->total_idx++;
|
||||
}
|
||||
|
||||
avi->strhdr_audio.length += (len >> 1);
|
||||
}
|
||||
// 同步一次
|
||||
if (avi->cache_idx == sizeof(avi->frame_list) / 4)
|
||||
{
|
||||
avimuxer_fix_data2(avi, 1);
|
||||
avi->cache_idx = 0;
|
||||
}
|
||||
avimuxer_audio2_end:
|
||||
return 0;
|
||||
}
|
||||
28
sdk/app/ffavimuxer/avimuxer.h
Normal file
28
sdk/app/ffavimuxer/avimuxer.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef __AVIMUXER_H__
|
||||
#define __AVIMUXER_H__
|
||||
#include "basic_include.h"
|
||||
#include <stdio.h>
|
||||
|
||||
enum
|
||||
{
|
||||
AVIMUXER_OK,
|
||||
AVIMUXER_FULL,
|
||||
AVIMUXER_ERR,
|
||||
};
|
||||
|
||||
void* avimuxer_init (char *file, int duration, int w, int h, int frate, int gop, int h265, int sampnum);
|
||||
void avimuxer_exit (void *ctx);
|
||||
unsigned int avimuxer_video(void *ctx, unsigned char *buf, int len, int key, unsigned pts);
|
||||
void avimuxer_audio(void *ctx, unsigned char *buf, int len, int key, unsigned pts);
|
||||
|
||||
void *avimuxer_init2(void *fp, uint32_t max_size, int w, int h, int frate, int gop, int h265, int sampnum);
|
||||
uint32_t avimuxer_video2(void *ctx, unsigned char *buf, int len, int key, unsigned pts,uint8_t insert);
|
||||
void avimuxer_exit2(void *ctx);
|
||||
uint32_t avimuxer_audio2(void *ctx, unsigned char *buf, int len, int key, unsigned pts);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
127
sdk/app/file_msi/file_msi.c
Normal file
127
sdk/app/file_msi/file_msi.c
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/fs/fatfs/osal_file.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "stream_define.h"
|
||||
|
||||
// data申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_LIBC_MALLOC av_malloc
|
||||
#define STREAM_LIBC_FREE av_free
|
||||
#define STREAM_LIBC_ZALLOC av_zalloc
|
||||
|
||||
#define FILE_MAX_RECV 64
|
||||
struct file_msi_s
|
||||
{
|
||||
os_task_t task;
|
||||
struct msi *msi;
|
||||
};
|
||||
|
||||
// 没有实现退出功能
|
||||
static void file_thread(void *d)
|
||||
{
|
||||
struct file_msi_s *file_s = (struct file_msi_s *) d;
|
||||
struct framebuff *fb;
|
||||
struct framebuff *tmp_fb;
|
||||
void *fp;
|
||||
msi_get(file_s->msi);
|
||||
struct file_msg_s *file_msg;
|
||||
uint32_t write_max_len;
|
||||
uint32_t write_len;
|
||||
uint32_t res;
|
||||
while (1)
|
||||
{
|
||||
fb = msi_get_fb(file_s->msi, -1);
|
||||
if (fb)
|
||||
{
|
||||
file_msg = (struct file_msg_s *) fb->priv;
|
||||
os_printf(KERN_INFO "file_msg->path:%s\tlen:%d\tishid:%d\n", file_msg->path,fb->len,file_msg->ishid);
|
||||
// 暂时没有考虑不存在是否需要创建文件夹
|
||||
fp = osal_fopen_auto((const char*)file_msg->path, "w+", file_msg->ishid);
|
||||
if (fp)
|
||||
{
|
||||
tmp_fb = fb;
|
||||
write_max_len = fb->len;
|
||||
while(tmp_fb && write_max_len)
|
||||
{
|
||||
if(!tmp_fb->clone)
|
||||
{
|
||||
write_len = write_max_len>tmp_fb->len?tmp_fb->len:write_max_len;
|
||||
write_max_len -= write_len;
|
||||
res = osal_fwrite(tmp_fb->data, write_len, 1, fp);
|
||||
if(!res)
|
||||
{
|
||||
os_printf(KERN_ERR"write file err:%d\n",get_errno());
|
||||
break;
|
||||
}
|
||||
}
|
||||
tmp_fb = tmp_fb->next;
|
||||
}
|
||||
|
||||
// 这里需要轮询,找到不是clone的模块
|
||||
osal_fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf(KERN_ERR"save file err:%d\n",get_errno());
|
||||
}
|
||||
msi_delete_fb(NULL, fb);
|
||||
}
|
||||
}
|
||||
msi_put(file_s->msi);
|
||||
}
|
||||
|
||||
int32_t file_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
struct file_msi_s *file_s = (struct file_msi_s *) msi->priv;
|
||||
(void)file_s;
|
||||
switch (cmd_id)
|
||||
{
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
}
|
||||
break;
|
||||
case MSI_CMD_PRE_DESTROY:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *fb = (struct framebuff *) param1;
|
||||
if (fb->mtype != F_FILE_T)
|
||||
{
|
||||
ret = RET_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *file_msi_init(const char *msi_name)
|
||||
{
|
||||
uint8_t is_new;
|
||||
struct file_msi_s *file_s;
|
||||
struct msi *msi = msi_new(msi_name, FILE_MAX_RECV, &is_new);
|
||||
if (is_new)
|
||||
{
|
||||
file_s = (struct file_msi_s *) STREAM_LIBC_ZALLOC(sizeof(struct file_msi_s));
|
||||
msi->priv = (void *) file_s;
|
||||
file_s->msi = msi;
|
||||
msi->action = file_msi_action;
|
||||
msi->enable = 1;
|
||||
OS_TASK_INIT("file_s_task", &file_s->task, file_thread, file_s, OS_TASK_PRIORITY_HIGH-1, NULL, 1500);
|
||||
}
|
||||
|
||||
return msi;
|
||||
}
|
||||
219
sdk/app/flash/flash_read_demo.c
Normal file
219
sdk/app/flash/flash_read_demo.c
Normal file
@@ -0,0 +1,219 @@
|
||||
#include "flash_read_demo.h"
|
||||
|
||||
// extern struct os_mutex *get_syscfg_lock();
|
||||
|
||||
uint8_t flash_read_uuid_demo(uint32_t addr)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
uint8_t id[128] = {0};
|
||||
struct hgxip_flash_custom_read flash_param;
|
||||
// struct os_mutex *mutex = get_syscfg_lock();
|
||||
|
||||
struct spi_nor_flash *flash = (void *)dev_get(HG_FLASH0_DEVID);
|
||||
spi_nor_open(flash);
|
||||
|
||||
//设置读取flash的参数命令
|
||||
flash_param.dummys = 8;
|
||||
flash_param.cmd = 0x4b; //flash读取id的命令
|
||||
flash_param.size = 128; //id正常是3byte,如果超过3byte,则会循环读取
|
||||
flash_param.addr = addr;
|
||||
flash_param.buf = id;
|
||||
// os_mutex_lock(mutex, osWaitForever);
|
||||
spi_nor_open(flash);
|
||||
spi_nor_custom_read(flash, (void*)&flash_param);
|
||||
|
||||
spi_nor_close(flash);
|
||||
// os_mutex_unlock(mutex);
|
||||
|
||||
for(int i=0;i<128;i++)
|
||||
{
|
||||
if(i%16 == 0)
|
||||
{
|
||||
_os_printf("\r\n");
|
||||
}
|
||||
_os_printf("%02X ",id[i]);
|
||||
}
|
||||
_os_printf("\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t flash_security_demo(uint32_t addr)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
uint8_t id[128] = {0};
|
||||
// struct os_mutex *mutex = get_syscfg_lock();
|
||||
|
||||
struct spi_nor_regval rval;
|
||||
|
||||
// os_mutex_lock(mutex, osWaitForever);
|
||||
struct spi_nor_flash *flash = (void *)dev_get(HG_FLASH0_DEVID);
|
||||
spi_nor_open(flash);
|
||||
|
||||
//擦除
|
||||
spi_nor_sec_erase(flash, addr);
|
||||
|
||||
// os_sleep_ms(1000);
|
||||
// //写入
|
||||
uint8_t buf[32] = "1234657890";
|
||||
rval.buff = buf;
|
||||
rval.size = 10;
|
||||
spi_nor_sec_program(flash, addr, &rval);
|
||||
|
||||
//读取
|
||||
rval.buff = id;
|
||||
rval.size = 128;
|
||||
spi_nor_sec_read(flash, addr, &rval);
|
||||
|
||||
spi_nor_close(flash);
|
||||
// os_mutex_unlock(mutex);
|
||||
|
||||
for(int i=0;i<128;i++)
|
||||
{
|
||||
if(i%16 == 0)
|
||||
{
|
||||
_os_printf("\r\n");
|
||||
}
|
||||
_os_printf("%02X ",id[i]);
|
||||
}
|
||||
_os_printf("\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//通过自定义方式去操作安全区(可能不同flash命令不一样)
|
||||
uint8_t flash_custom_security_demo(uint32_t addr)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
uint8_t id[128] = {0};
|
||||
struct hgxip_flash_custom_read flash_param;
|
||||
// struct os_mutex *mutex = get_syscfg_lock();
|
||||
|
||||
struct spi_nor_flash *flash = (void *)dev_get(HG_FLASH0_DEVID);
|
||||
spi_nor_open(flash);
|
||||
|
||||
//设置读取flash的参数命令
|
||||
flash_param.dummys = 0;
|
||||
flash_param.cmd = 0x42; //flash读取id的命令
|
||||
flash_param.size = 128; //id正常是3byte,如果超过3byte,则会循环读取
|
||||
flash_param.addr = addr;
|
||||
flash_param.buf = id;
|
||||
// os_mutex_lock(mutex, osWaitForever);
|
||||
spi_nor_open(flash);
|
||||
|
||||
|
||||
//擦除只需要命令和地址(接口暂时支持这个,有特殊flash需要作兼容)
|
||||
flash_param.cmd = 0x44;
|
||||
spi_nor_custom_erase(flash, (void *)&flash_param);
|
||||
|
||||
//写入数据到对应区域,需要设置dummys buf 长度 以及命令
|
||||
memcpy(id,"abcdefghij",10);
|
||||
flash_param.size = 10;
|
||||
flash_param.cmd = 0x42;
|
||||
flash_param.dummys = 0;
|
||||
spi_nor_custom_write(flash, (void *)&flash_param);
|
||||
|
||||
//读取数据,需要设置dummys 命令 buf size
|
||||
memset(id,0,sizeof(id));
|
||||
flash_param.cmd = 0x48;
|
||||
flash_param.dummys = 8;
|
||||
flash_param.size = sizeof(id);
|
||||
spi_nor_custom_read(flash, (void *)&flash_param);
|
||||
|
||||
|
||||
spi_nor_close(flash);
|
||||
// os_mutex_unlock(mutex);
|
||||
|
||||
for(int i=0;i<128;i++)
|
||||
{
|
||||
if(i%16 == 0)
|
||||
{
|
||||
_os_printf("\r\n");
|
||||
}
|
||||
_os_printf("%02X ",id[i]);
|
||||
}
|
||||
_os_printf("\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t flash_rdwr_demo(uint32_t addr)
|
||||
{
|
||||
uint32_t sector_addr = addr & (~0xfff);
|
||||
uint8_t buf[512];
|
||||
struct spi_nor_flash *flash = (void *)dev_get(HG_FLASH0_DEVID);
|
||||
spi_nor_open(flash);
|
||||
printf("erase addr 0x%x\r\n", sector_addr);
|
||||
spi_nor_sector_erase(flash, sector_addr);
|
||||
spi_nor_read(flash, sector_addr, buf, sizeof(buf));
|
||||
for(int i = 0;i<sizeof(buf);i++)
|
||||
{
|
||||
buf[i] = i & 0xff;
|
||||
}
|
||||
spi_nor_write(flash, sector_addr, buf, sizeof(buf));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
spi_nor_read(flash, sector_addr, buf, sizeof(buf));
|
||||
for(int i = 0;i<512;i++)
|
||||
{
|
||||
if (buf[i] != (i&0xff)) {
|
||||
printf("flash rdwr fail\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0;i<128;i++)
|
||||
{
|
||||
if(i%16 == 0)
|
||||
{
|
||||
_os_printf("\r\n");
|
||||
}
|
||||
_os_printf("%02X ",buf[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t flash_reg_opt_demo(void)
|
||||
{
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
uint8_t buf[4] = {0};
|
||||
struct hgxip_flash_reg_opt_param opt_param;
|
||||
// struct os_mutex *mutex = get_syscfg_lock();
|
||||
struct spi_nor_flash *flash = (void *)dev_get(HG_FLASH0_DEVID);
|
||||
spi_nor_open(flash);
|
||||
|
||||
// os_mutex_lock(mutex, osWaitForever);
|
||||
spi_nor_open(flash);
|
||||
|
||||
//SR = 0
|
||||
//buf[0] = 0;
|
||||
//opt_param.buf = buf;
|
||||
//opt_param.cmd = 0x1;
|
||||
//opt_param.pre_cmd = 0x06;
|
||||
//opt_param.len = 1;
|
||||
//spi_ioctl(flash->spidev, SPI_XIP_REG_OPT, (uint32)&opt_param, 0);
|
||||
|
||||
//read flash status reg
|
||||
opt_param.buf = buf;
|
||||
opt_param.cmd = 0x5;
|
||||
opt_param.pre_cmd = 0xFF;
|
||||
opt_param.len = 4;
|
||||
spi_ioctl(flash->spidev, SPI_XIP_REG_OPT, (uint32)&opt_param, 0);
|
||||
os_printf("0x05 0x%x\r\n", buf[0]);
|
||||
|
||||
opt_param.buf = buf;
|
||||
opt_param.cmd = 0x35;
|
||||
opt_param.pre_cmd = 0xFF;
|
||||
opt_param.len = 4;
|
||||
spi_ioctl(flash->spidev, SPI_XIP_REG_OPT, (uint32)&opt_param, 0);
|
||||
os_printf("0x35 0x%x\r\n", buf[0]);
|
||||
|
||||
opt_param.buf = buf;
|
||||
opt_param.cmd = 0x15;
|
||||
opt_param.pre_cmd = 0xFF;
|
||||
opt_param.len = 4;
|
||||
spi_ioctl(flash->spidev, SPI_XIP_REG_OPT, (uint32)&opt_param, 0);
|
||||
os_printf("0x15 0x%x\r\n", buf[0]);
|
||||
spi_nor_close(flash);
|
||||
// os_mutex_unlock(mutex);
|
||||
return 0;
|
||||
}
|
||||
22
sdk/app/flash/flash_read_demo.h
Normal file
22
sdk/app/flash/flash_read_demo.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef __FLASH_READ_DEMO_H
|
||||
#define __FLASH_READ_DEMO_H
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "errno.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "osal/irq.h"
|
||||
#include "osal/task.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "hal/spi.h"
|
||||
#include "hal/spi_nor.h"
|
||||
#include "hal/crc.h"
|
||||
#include "lib/syscfg/syscfg.h"
|
||||
|
||||
#include "dev/spi/hgspi_xip.h"
|
||||
|
||||
|
||||
uint8_t flash_read_uuid_demo();
|
||||
#endif
|
||||
246
sdk/app/gsensor/g_sensor.c
Normal file
246
sdk/app/gsensor/g_sensor.c
Normal file
@@ -0,0 +1,246 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "g_sensor.h"
|
||||
#include "devid.h"
|
||||
#include "sys_config.h"
|
||||
#include "hal/gpio.h"
|
||||
#include "osal/irq.h"
|
||||
#include "osal/string.h"
|
||||
#include "dev/csi/hgdvp.h"
|
||||
#include "osal/sleep.h"
|
||||
|
||||
static _Gsensor_Ident_ *devGsensorInit=NULL;
|
||||
|
||||
uint8_t gSensorwriteID,gSensorreadID;
|
||||
uint8_t gAddrbytnum,gDatabytnum;
|
||||
|
||||
struct i2c_device *g_sensor_iic;
|
||||
|
||||
static const _Gsensor_Ident_ *devGsensorInitTable[] = {
|
||||
#if DEV_GSENSOR_DA280
|
||||
&da280_init,
|
||||
#endif
|
||||
|
||||
#if DEV_GSENSOR_QMA7981
|
||||
&qma7981_init,
|
||||
#endif
|
||||
|
||||
#if DEV_GSENSOR_SC7A20
|
||||
&sc7a20_init,
|
||||
#endif
|
||||
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
static const _Gsensor_Adpt_ *devGsensorOPTable[] = {
|
||||
|
||||
#if DEV_GSENSOR_DA280
|
||||
&da280_cmd,
|
||||
#endif
|
||||
|
||||
#if DEV_GSENSOR_QMA7981
|
||||
&qma7981_cmd,
|
||||
#endif
|
||||
|
||||
#if DEV_GSENSOR_SC7A20
|
||||
&sc7a20_cmd,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
uint8_t x_addr_l,x_addr_h,y_addr_l,y_addr_h,z_addr_l,z_addr_h;
|
||||
|
||||
|
||||
void Delay_nopCnt(uint32_t cnt);
|
||||
void delay_us(uint32 n);
|
||||
|
||||
const _Gsensor_Ident_ gnull_init={0x00,0x00,0x00,0x00,0x00,0x00};
|
||||
|
||||
static int gsensorCheckId(struct i2c_device *p_iic,const _Gsensor_Ident_ *p_sensor_ident)
|
||||
{
|
||||
uint8_t u8Buf[3];
|
||||
uint32_t id= 0;
|
||||
|
||||
|
||||
gSensorwriteID = p_sensor_ident->w_cmd;
|
||||
gSensorreadID =p_sensor_ident->r_cmd;
|
||||
gAddrbytnum = p_sensor_ident->addr_num;
|
||||
gDatabytnum = p_sensor_ident->data_num;
|
||||
|
||||
u8Buf[0] = p_sensor_ident->id_reg;
|
||||
if(p_sensor_ident->addr_num == 2)
|
||||
{
|
||||
u8Buf[0] = p_sensor_ident->id_reg>>8;
|
||||
u8Buf[1] = p_sensor_ident->id_reg;
|
||||
}
|
||||
|
||||
|
||||
_os_printf("addr:%x %x %x %x\r\n",p_sensor_ident->addr_num,p_sensor_ident->data_num,gSensorwriteID,gSensorreadID);
|
||||
i2c_ioctl(p_iic,IIC_SET_DEVICE_ADDR,gSensorwriteID>>1);
|
||||
//id = i2c_sensor_read(p_iic,u8Buf,p_sensor_ident->addr_num,p_sensor_ident->data_num,gSensorwriteID,gSensorreadID);
|
||||
i2c_read(p_iic,(int8*)u8Buf,p_sensor_ident->addr_num,(int8*)&id,p_sensor_ident->data_num);
|
||||
_os_printf("SID: %x, %x, %x, %x,%x\r\n",id,p_sensor_ident->id,gSensorwriteID,gSensorreadID,p_sensor_ident->id_reg);
|
||||
if(id == p_sensor_ident->id)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static _Gsensor_Adpt_ * gsensorAutoCheck(struct i2c_device *p_iic,uint8_t *init_buf)
|
||||
{
|
||||
uint8_t i;
|
||||
_Gsensor_Adpt_ * devSensor_Struct=NULL;
|
||||
for(i=0;devGsensorInitTable[i] != NULL;i++)
|
||||
{
|
||||
if(gsensorCheckId(p_iic,devGsensorInitTable[i])>=0)
|
||||
{
|
||||
_os_printf("id =%x num:%d \n",devGsensorInitTable[i]->id,i);
|
||||
devGsensorInit = (_Gsensor_Ident_ *) devGsensorInitTable[i];
|
||||
devSensor_Struct = (_Gsensor_Adpt_ *) devGsensorOPTable[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(devSensor_Struct == NULL)
|
||||
{
|
||||
_os_printf("Er: unkown!");
|
||||
devGsensorInit = (_Gsensor_Ident_ *)&gnull_init;
|
||||
return NULL; // index 0 is test only
|
||||
}
|
||||
return devSensor_Struct;
|
||||
}
|
||||
|
||||
uint8_t get_gsensor_x_y_z(uint8_t* buf){
|
||||
int itk = 0;
|
||||
buf[0] = 0x04;
|
||||
buf[2] = 0x05;
|
||||
buf[4] = 0x06;
|
||||
buf[6] = 0x07;
|
||||
for(itk = 0;itk < 8;itk=itk+2){
|
||||
i2c_read(g_sensor_iic,(int8 *)&buf[itk],gAddrbytnum,(int8*)&buf[itk+1],gDatabytnum);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t get_gsensor_x(uint8_t* buf){
|
||||
int itk = 0;
|
||||
buf[0] = x_addr_l;
|
||||
buf[2] = x_addr_h;
|
||||
for(itk = 0;itk < 4;itk=itk+2){
|
||||
i2c_read(g_sensor_iic,(int8 *)&buf[itk],gAddrbytnum,(int8*)&buf[itk+1],gDatabytnum);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t get_gsensor_y(uint8_t* buf){
|
||||
int itk = 0;
|
||||
buf[0] = y_addr_l;
|
||||
buf[2] = y_addr_h;
|
||||
for(itk = 0;itk < 4;itk=itk+2){
|
||||
i2c_read(g_sensor_iic,(int8 *)&buf[itk],gAddrbytnum,(int8*)&buf[itk+1],gDatabytnum);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t get_gsensor_z(uint8_t* buf){
|
||||
int itk = 0;
|
||||
buf[0] = z_addr_l;
|
||||
buf[2] = z_addr_h;
|
||||
for(itk = 0;itk < 4;itk=itk+2){
|
||||
i2c_read(g_sensor_iic,(int8 *)&buf[itk],gAddrbytnum,(int8*)&buf[itk+1],gDatabytnum);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t g_sensor_init(){
|
||||
static _Gsensor_Adpt_ *p_gsensor_cmd = NULL;
|
||||
int i,j;
|
||||
uint8_t buf[5];
|
||||
uint8_t ack;
|
||||
|
||||
g_sensor_iic = (struct i2c_device *)dev_get(HG_I2C1_DEVID);
|
||||
x_addr_l = x_addr_h = y_addr_l = y_addr_h = z_addr_l = z_addr_h = 0;
|
||||
|
||||
_os_printf("g_sensor_init start,iic init:%x\r\n",(int)g_sensor_iic);
|
||||
|
||||
//G_sensor_test();
|
||||
//while(1);
|
||||
//iic_init_sensor(G_IIC_CLK,GSENSOR_IIC);
|
||||
//i2c_SendStop(GSENSOR_IIC);
|
||||
|
||||
i2c_open(g_sensor_iic, IIC_MODE_MASTER, IIC_ADDR_7BIT, 0);
|
||||
i2c_set_baudrate(g_sensor_iic,G_IIC_CLK);
|
||||
i2c_ioctl(g_sensor_iic,IIC_SDA_OUTPUT_DELAY,20);
|
||||
i2c_ioctl(g_sensor_iic,IIC_FILTERING,20);
|
||||
//i2c_send_stop(g_sensor_iic);
|
||||
|
||||
_os_printf("init g_sensor,check id\r\n");
|
||||
p_gsensor_cmd = gsensorAutoCheck(g_sensor_iic,NULL);
|
||||
if(p_gsensor_cmd == NULL){
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(p_gsensor_cmd->preread!=NULL)
|
||||
{
|
||||
|
||||
for(i=0;;i+=gAddrbytnum)
|
||||
{
|
||||
if((p_gsensor_cmd->preread[i]==0xFF)&&(p_gsensor_cmd->preread[i+1]==0xFF)){
|
||||
_os_printf("init pre table num:%d\r\n",i);
|
||||
break;
|
||||
}
|
||||
if((p_gsensor_cmd->preread[i]==0xFC)||(p_gsensor_cmd->preread[i]==0xFD)){
|
||||
i += 1;
|
||||
if(p_gsensor_cmd->preread[i]==0xFC){
|
||||
os_sleep_ms(p_gsensor_cmd->preread[i+1]);
|
||||
}else{
|
||||
delay_us(p_gsensor_cmd->preread[i+1]);
|
||||
}
|
||||
}else{
|
||||
for(j = 0; j < gAddrbytnum;j++){
|
||||
buf[j] = p_gsensor_cmd->preread[i+j];
|
||||
}
|
||||
//ret = i2c_sensor_read(g_sensor_iic,buf,gAddrbytnum,gDatabytnum,gSensorwriteID,gSensorreadID);
|
||||
i2c_read(g_sensor_iic,(int8 *)buf,gAddrbytnum,(int8*)&ack,gDatabytnum);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(p_gsensor_cmd->init!=NULL)
|
||||
{
|
||||
x_addr_l = p_gsensor_cmd->local_xyz.x_l;
|
||||
x_addr_h = p_gsensor_cmd->local_xyz.x_h;
|
||||
y_addr_l = p_gsensor_cmd->local_xyz.y_l;
|
||||
y_addr_h = p_gsensor_cmd->local_xyz.y_h;
|
||||
z_addr_l = p_gsensor_cmd->local_xyz.z_l;
|
||||
z_addr_h = p_gsensor_cmd->local_xyz.z_h;
|
||||
for(i=0;;i+=gAddrbytnum+gDatabytnum)
|
||||
{
|
||||
if((p_gsensor_cmd->init[i]==0xFF)&&(p_gsensor_cmd->init[i+1]==0xFF)){
|
||||
_os_printf("init table num:%d\r\n",i);
|
||||
break;
|
||||
}
|
||||
if((p_gsensor_cmd->init[i]==0xFC)||(p_gsensor_cmd->init[i]==0xFD)){
|
||||
if(p_gsensor_cmd->init[i]==0xFC){
|
||||
os_sleep_ms(p_gsensor_cmd->init[i+1]);
|
||||
}else{
|
||||
delay_us(p_gsensor_cmd->init[i+1]);
|
||||
}
|
||||
}else{
|
||||
//i2c_sensor_write(g_sensor_iic,&p_gsensor_cmd->init[i],gAddrbytnum,gDatabytnum,gSensorwriteID,gSensorreadID);
|
||||
i2c_write(g_sensor_iic, (int8*)&p_gsensor_cmd->init[i], gAddrbytnum, (int8*)&p_gsensor_cmd->init[i+gAddrbytnum], gDatabytnum);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
66
sdk/app/gsensor/g_sensor.h
Normal file
66
sdk/app/gsensor/g_sensor.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef _G_SENSOR_H_
|
||||
#define _G_SENSOR_H_
|
||||
#include "tx_platform.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "hal/i2c.h"
|
||||
|
||||
|
||||
#ifndef ALIGNED
|
||||
#define ALIGNED(x) __attribute__ ((aligned(x)))
|
||||
#endif
|
||||
#define GSENSOR_INIT_SECTION ALIGNED(32)
|
||||
#define GSENSOR_OP_SECTION ALIGNED(32)
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8 x_l;
|
||||
uint8 x_h;
|
||||
uint8 y_l;
|
||||
uint8 y_h;
|
||||
uint8 z_l;
|
||||
uint8 z_h;
|
||||
} local;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8 * init;
|
||||
uint8 * preread;
|
||||
local local_xyz;
|
||||
} _Gsensor_Adpt_;
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 id,w_cmd,r_cmd,addr_num,data_num;
|
||||
uint16 id_reg;
|
||||
}_Gsensor_Ident_;
|
||||
|
||||
|
||||
#define G_IIC_CLK 346000UL
|
||||
|
||||
|
||||
|
||||
#define DEV_GSENSOR_DA280 1
|
||||
#define DEV_GSENSOR_QMA7981 0
|
||||
#define DEV_GSENSOR_SC7A20 0
|
||||
|
||||
|
||||
#if DEV_GSENSOR_DA280
|
||||
extern const _Gsensor_Ident_ da280_init;
|
||||
extern GSENSOR_OP_SECTION const _Gsensor_Adpt_ da280_cmd;
|
||||
#endif
|
||||
|
||||
#if DEV_GSENSOR_QMA7981
|
||||
extern const _Gsensor_Ident_ qma7981_init;
|
||||
extern GSENSOR_OP_SECTION const _Gsensor_Adpt_ qma7981_cmd;
|
||||
#endif
|
||||
|
||||
#if DEV_GSENSOR_SC7A20
|
||||
extern const _Gsensor_Ident_ sc7a20_init;
|
||||
extern GSENSOR_OP_SECTION const _Gsensor_Adpt_ sc7a20_cmd;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
107
sdk/app/http/certs.h
Normal file
107
sdk/app/http/certs.h
Normal file
@@ -0,0 +1,107 @@
|
||||
#ifndef CERTS_H_
|
||||
#define CERTS_H_
|
||||
|
||||
static const char *s_ssl_cert =
|
||||
"-----BEGIN CERTIFICATE-----\r\n" \
|
||||
"MIIBhzCCASygAwIBAgIUbnMoVd8TtWH1T09dANkK2LU6IUswCgYIKoZIzj0EAwIw\r\n" \
|
||||
"RDELMAkGA1UEBhMCSUUxDzANBgNVBAcMBkR1YmxpbjEQMA4GA1UECgwHQ2VzYW50\r\n" \
|
||||
"YTESMBAGA1UEAwwJVGVzdCBSb290MB4XDTIwMDUwOTIxNTE0OVoXDTMwMDUwOTIx\r\n" \
|
||||
"NTE0OVowETEPMA0GA1UEAwwGc2VydmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\r\n" \
|
||||
"QgAEkuBGnInDN6l06zVVQ1VcrOvH5FDu9MC6FwJc2e201P8hEpq0Q/SJS2nkbSuW\r\n" \
|
||||
"H/wBTTBaeXN2uhlBzMUWK790KKMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gw\r\n" \
|
||||
"EwYDVR0lBAwwCgYIKwYBBQUHAwEwCgYIKoZIzj0EAwIDSQAwRgIhAPo6xx7LjCdZ\r\n" \
|
||||
"QY133XvLjAgVFrlucOZHONFVQuDXZsjwAiEAzHBNligA08c5U3SySYcnkhurGg50\r\n" \
|
||||
"BllCI0eYQ9ggp/o=\r\n" \
|
||||
"-----END CERTIFICATE-----\r\n";
|
||||
|
||||
static const char *s_ssl_key =
|
||||
"-----BEGIN PRIVATE KEY-----\r\n" \
|
||||
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQglNni0t9Dg9icgG8w\r\n" \
|
||||
"kbfxWSS+TuNgbtNybIQXcm3NHpmhRANCAASS4EacicM3qXTrNVVDVVys68fkUO70\r\n" \
|
||||
"wLoXAlzZ7bTU/yESmrRD9IlLaeRtK5Yf/AFNMFp5c3a6GUHMxRYrv3Qo\r\n" \
|
||||
"-----END PRIVATE KEY-----\r\n";
|
||||
|
||||
|
||||
static const char *s_ca =
|
||||
"-\n"
|
||||
"Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA\n"
|
||||
"Not Before: Nov 10 00:00:00 2006 GMT\n"
|
||||
"Not After : Nov 10 00:00:00 2031 GMT\n"
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs\n"
|
||||
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
|
||||
"d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\n"
|
||||
"ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL\n"
|
||||
"MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3\n"
|
||||
"LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug\n"
|
||||
"RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm\n"
|
||||
"+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW\n"
|
||||
"PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM\n"
|
||||
"xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB\n"
|
||||
"Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3\n"
|
||||
"hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg\n"
|
||||
"EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF\n"
|
||||
"MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA\n"
|
||||
"FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec\n"
|
||||
"nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z\n"
|
||||
"eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF\n"
|
||||
"hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2\n"
|
||||
"Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe\n"
|
||||
"vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep\n"
|
||||
"+OkuE6N36B9K\n"
|
||||
"-----END CERTIFICATE-----\n"
|
||||
"\n"
|
||||
"Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA\n"
|
||||
"Not Before: Nov 10 00:00:00 2006 GMT\n"
|
||||
"Not After : Nov 10 00:00:00 2031 GMT\n"
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n"
|
||||
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
|
||||
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n"
|
||||
"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n"
|
||||
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
|
||||
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n"
|
||||
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n"
|
||||
"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n"
|
||||
"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n"
|
||||
"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n"
|
||||
"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n"
|
||||
"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n"
|
||||
"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n"
|
||||
"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n"
|
||||
"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n"
|
||||
"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n"
|
||||
"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n"
|
||||
"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n"
|
||||
"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n"
|
||||
"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n"
|
||||
"-----END CERTIFICATE-----\n"
|
||||
"\n"
|
||||
"Not Before: Nov 10 00:00:00 2006 GMT\n"
|
||||
"Not After : Nov 10 00:00:00 2031 GMT\n"
|
||||
"Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA\n"
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n"
|
||||
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
|
||||
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n"
|
||||
"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n"
|
||||
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
|
||||
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n"
|
||||
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n"
|
||||
"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n"
|
||||
"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n"
|
||||
"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n"
|
||||
"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n"
|
||||
"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n"
|
||||
"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n"
|
||||
"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n"
|
||||
"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n"
|
||||
"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n"
|
||||
"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n"
|
||||
"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n"
|
||||
"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n"
|
||||
"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n"
|
||||
"-----END CERTIFICATE-----\n"
|
||||
"\n"
|
||||
"";
|
||||
#endif
|
||||
153
sdk/app/http/http_client_demo/http_client_demo.c
Normal file
153
sdk/app/http/http_client_demo/http_client_demo.c
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright (c) 2021 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// Example HTTP client. Connect to `s_url`, send request, wait for a response,
|
||||
// print the response and exit.
|
||||
// You can change `s_url` from the command line by executing: ./example YOUR_URL
|
||||
//
|
||||
// To enable SSL/TLS, make SSL=OPENSSL or make SSL=MBEDTLS
|
||||
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "osal/irq.h"
|
||||
#include "osal/work.h"
|
||||
#include "osal/sleep.h"
|
||||
#include "osal/timer.h"
|
||||
#include "hal/gpio.h"
|
||||
#include "lib/common/common.h"
|
||||
#include "lib/common/sysevt.h"
|
||||
#include "lib/syscfg/syscfg.h"
|
||||
#include <string.h>
|
||||
#if HTTPS_CLIENT || HTTP_CLIENT
|
||||
#include "mongoose.h"
|
||||
#include "http_client_demo.h"
|
||||
#include "certs.h"
|
||||
// The very first web page in history. You can replace it from command line
|
||||
#if HTTPS_CLIENT
|
||||
static const char *s_url = "https://example.org/";//AP模式下无法透传上网
|
||||
#elif HTTP_CLIENT
|
||||
static const char *s_url = "http://192.168.1.100";
|
||||
#else
|
||||
static const char *s_url = "";
|
||||
#endif
|
||||
static const char *s_post_data = NULL; // POST data
|
||||
static const uint64_t s_timeout_ms = 1500; // Connect timeout in milliseconds
|
||||
|
||||
static struct mg_str *get_header_value(struct mg_http_message *hm,const char *name);
|
||||
|
||||
// Print HTTP response and signal that we're done
|
||||
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||
if (ev == MG_EV_OPEN) {
|
||||
// Connection created. Store connect expiration time in c->data
|
||||
*(uint64_t *) c->data = mg_millis() + s_timeout_ms;
|
||||
} else if (ev == MG_EV_POLL) {
|
||||
if (mg_millis() > *(uint64_t *) c->data &&
|
||||
(c->is_connecting || c->is_resolving)) {
|
||||
mg_error(c, "Connect timeout");
|
||||
}
|
||||
} else if (ev == MG_EV_CONNECT) {
|
||||
// Connected to server. Extract host name from URL
|
||||
struct mg_str host = mg_url_host(s_url);
|
||||
|
||||
// If s_url is https://, tell client connection to use TLS
|
||||
if (mg_url_is_ssl(s_url)) {
|
||||
struct mg_tls_opts opts = {
|
||||
//.ca = s_ca,
|
||||
.srvname = host
|
||||
};
|
||||
mg_tls_init(c, &opts);
|
||||
}
|
||||
|
||||
// Send request
|
||||
int content_length = s_post_data ? strlen(s_post_data) : 0;
|
||||
mg_printf(c,
|
||||
"%s %s HTTP/1.0\r\n"
|
||||
"Host: %.*s\r\n"
|
||||
"Content-Type: octet-stream\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"\r\n",
|
||||
s_post_data ? "POST" : "GET", mg_url_uri(s_url), (int) host.len,
|
||||
host.ptr, content_length);
|
||||
mg_send(c, s_post_data, content_length);
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
// Response is received. Print it
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
get_header_value(hm,"Content-Type");
|
||||
MG_INFO(("%.*s", (int) hm->message.len, hm->message.ptr));
|
||||
c->is_closing = 1; // Tell mongoose to close this connection
|
||||
*(bool *) fn_data = true; // Tell event loop to stop
|
||||
} else if (ev == MG_EV_ERROR) {
|
||||
*(bool *) fn_data = true; // Error, tell event loop to stop
|
||||
}
|
||||
}
|
||||
|
||||
os_task_t http_client_task;
|
||||
|
||||
int http_client_demo(void *arg) {
|
||||
|
||||
struct mg_mgr mgr; // Event manager
|
||||
bool done = false; // Event handler flips it to true
|
||||
mg_log_set(MG_LL_DEBUG); // Set to 0 to disable debug
|
||||
mg_mgr_init(&mgr); // Initialise event manager
|
||||
|
||||
mg_http_connect(&mgr, s_url, fn, &done); // Create client connection
|
||||
while (!done) mg_mgr_poll(&mgr, 50); // Event manager loops until 'done'
|
||||
mg_mgr_free(&mgr); // Free resources
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sysevt_hdl_res dhcp_client_get_ip(uint32 event_id, uint32 data, uint32 priv)
|
||||
{
|
||||
static uint8_t is_get_ip = 0;
|
||||
printf("%s:%d!!!!!!!!!!!\n",__FUNCTION__,__LINE__);
|
||||
if(!is_get_ip)
|
||||
{
|
||||
is_get_ip = 1;
|
||||
OS_TASK_INIT("http_client_task", &http_client_task, http_client_demo, NULL, OS_TASK_PRIORITY_NORMAL, 20*1024);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int http_client_init(uint32 ip)
|
||||
{
|
||||
|
||||
printf("%s:%d\tip:%s\n",__FUNCTION__,__LINE__,inet_ntoa(ip));
|
||||
|
||||
sys_event_take(SYS_EVENT(SYS_EVENT_WIFI, SYSEVT_WIFI_STA_CONNECTTED),dhcp_client_get_ip,0);
|
||||
//if(!ip)
|
||||
//{
|
||||
// sys_event_take(SYS_EVENT(SYS_EVENT_NETWORK, SYSEVT_LWIP_DHCPC_DONE),dhcp_client_get_ip,0);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// OS_TASK_INIT("http_client_task", &http_client_task, http_client_demo, NULL, OS_TASK_PRIORITY_NORMAL, 10*1024);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mg_str *get_header_value(struct mg_http_message *hm,const char *name) {
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
struct mg_str *cl;
|
||||
if ((cl = mg_http_get_header(hm, name)) != NULL) {
|
||||
printf("%s--get %s %.*s\r\n", __FILE__, name, (int) cl->len, cl->ptr);
|
||||
return cl;
|
||||
} else {
|
||||
printf("%s--can not get %s %.*s\r\n", __FILE__, name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
7
sdk/app/http/http_client_demo/http_client_demo.h
Normal file
7
sdk/app/http/http_client_demo/http_client_demo.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef HTTPS_CLIENT_H
|
||||
#define HTTPS_CLIENT_H
|
||||
|
||||
#define HTTP_DIR "0:/HTTP"
|
||||
|
||||
int http_client_init(uint32 ip);
|
||||
#endif
|
||||
151
sdk/app/http/http_server_demo/http_server_demo.c
Normal file
151
sdk/app/http/http_server_demo/http_server_demo.c
Normal file
@@ -0,0 +1,151 @@
|
||||
// Copyright (c) 2020 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// HTTP server example. This server serves both static and dynamic content.
|
||||
// It opens two ports: plain HTTP on port 8000 and HTTP on port 8443.
|
||||
// It implements the following endpoints:
|
||||
// /api/stats - respond with free-formatted stats on current connections
|
||||
// /api/f2/:id - wildcard example, respond with JSON string {"result": "URI"}
|
||||
// any other URI serves static files from s_root_dir
|
||||
//
|
||||
// To enable SSL/TLS (using self-signed certificates in PEM files),
|
||||
// 1. make SSL=OPENSSL or make SSL=MBEDTLS
|
||||
// 2. curl -k https://127.0.0.1:8443
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "osal/irq.h"
|
||||
#include "osal/work.h"
|
||||
#include "osal/sleep.h"
|
||||
#include "osal/timer.h"
|
||||
#include "hal/gpio.h"
|
||||
#include "lib/common/common.h"
|
||||
#include "lib/common/sysevt.h"
|
||||
#include "lib/syscfg/syscfg.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "netif/ethernetif.h"
|
||||
#include <string.h>
|
||||
#if HTTP_SERVER || HTTPS_SERVER
|
||||
#include "mongoose.h"
|
||||
#include "http_server_demo.h"
|
||||
#include "certs.h"
|
||||
static char s_http_addr[30] = "http://"; // HTTP port
|
||||
static char s_https_addr[30] = "https://"; // HTTPS port
|
||||
static const char *s_root_dir = ".";
|
||||
os_task_t http_server_task;
|
||||
// We use the same event handler function for HTTP and HTTPS connections
|
||||
// fn_data is NULL for plain HTTP, and non-NULL for HTTPS
|
||||
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||
if (ev == MG_EV_ACCEPT && fn_data != NULL) {
|
||||
printf("ev == MG_EV_ACCEPT && fn_data != NULL\r\n");
|
||||
struct mg_tls_opts opts = {
|
||||
//.ca = s_ca,//双向验证,一般不用
|
||||
.cert = s_ssl_cert,
|
||||
.certkey = s_ssl_key
|
||||
};
|
||||
mg_tls_init(c, &opts);
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
MG_INFO(("%.*s %.*s %ld", (int) hm->method.len, hm->method.ptr,
|
||||
(int) hm->uri.len, hm->uri.ptr, (long) hm->body.len));
|
||||
if (mg_http_match_uri(hm, "/api/stats")) {
|
||||
// Print some statistics about currently established connections
|
||||
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
||||
mg_http_printf_chunk(c, "ID PROTO TYPE LOCAL REMOTE\n");
|
||||
for (struct mg_connection *t = c->mgr->conns; t != NULL; t = t->next) {
|
||||
(c, "%-3lu %4s %s %I %I\n", t->id,
|
||||
t->is_udp ? "UDP" : "TCP",
|
||||
t->is_listening ? "LISTENING"
|
||||
: t->is_accepted ? "ACCEPTED "
|
||||
: "CONNECTED",
|
||||
4, &t->loc.ip, 4, &t->rem.ip);
|
||||
}
|
||||
mg_http_printf_chunk(c, ""); // Don't forget the last empty chunk
|
||||
} else if (mg_http_match_uri(hm, "/api/f2/*")) {
|
||||
mg_http_reply(c, 200, "", "{\"result\": \"%.*s\"}\n", (int) hm->uri.len,
|
||||
hm->uri.ptr);
|
||||
} else {
|
||||
struct mg_http_serve_opts opts = {.root_dir = s_root_dir};
|
||||
|
||||
mg_http_serve_dir(c, ev_data, &opts);
|
||||
}
|
||||
}
|
||||
(void) fn_data;
|
||||
}
|
||||
|
||||
int http_server_demo(void) {
|
||||
struct mg_mgr mgr; // Event manager
|
||||
mg_log_set(MG_LL_DEBUG); // Set log level
|
||||
mg_mgr_init(&mgr); // Initialise event manager
|
||||
#if HTTP_SERVER
|
||||
mg_http_listen(&mgr, s_http_addr, fn, NULL); // Create HTTP listener
|
||||
#elif HTTPS_SERVER
|
||||
mg_http_listen(&mgr, s_https_addr, fn, (void *) 1); // HTTPS listener
|
||||
#endif
|
||||
for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
||||
mg_mgr_free(&mgr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sysevt_hdl_res dhcp_client_get_ip(uint32 event_id, uint32 data, uint32 priv)
|
||||
{
|
||||
static uint8_t is_get_ip = 0;
|
||||
printf("%s:%d!!!!!!!!!!!\n",__FUNCTION__,__LINE__);
|
||||
if(!is_get_ip)
|
||||
{
|
||||
ip_addr_t ipaddr;
|
||||
char *ip;
|
||||
is_get_ip = 1;
|
||||
ipaddr = lwip_netif_get_ip2("w0");
|
||||
ip = inet_ntoa(ipaddr);
|
||||
#if HTTP_SERVER
|
||||
strncat(s_http_addr,ip,strlen(ip));
|
||||
printf("server_ip: %s\r\n", s_http_addr);
|
||||
#elif HTTPS_SERVER
|
||||
strncat(s_https_addr,ip,strlen(ip));
|
||||
printf("server_ip: %s\r\n", s_https_addr);
|
||||
#endif
|
||||
|
||||
OS_TASK_INIT("http", &http_server_task, http_server_demo, NULL, OS_TASK_PRIORITY_NORMAL, 20*1024);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int http_server_init(uint32 ip)
|
||||
{
|
||||
|
||||
printf("%s:%d\tip:%X\n",__FUNCTION__,__LINE__,ip);
|
||||
|
||||
|
||||
if(!ip)
|
||||
{
|
||||
sys_event_take(SYS_EVENT(SYS_EVENT_NETWORK, SYSEVT_LWIP_DHCPC_DONE),dhcp_client_get_ip,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ip_addr_t ipaddr;
|
||||
char *ip;
|
||||
ipaddr = lwip_netif_get_ip2("w0");
|
||||
ip = inet_ntoa(ipaddr);
|
||||
#if HTTP_SERVER
|
||||
strncat(s_http_addr,ip,strlen(ip));
|
||||
printf("server_ip: %s\r\n", s_http_addr);
|
||||
#elif HTTPS_SERVER
|
||||
strncat(s_https_addr,ip,strlen(ip));
|
||||
printf("server_ip: %s\r\n", s_https_addr);
|
||||
#endif
|
||||
OS_TASK_INIT("http", &http_server_task, http_server_demo, NULL, OS_TASK_PRIORITY_NORMAL, 20*1024);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
6
sdk/app/http/http_server_demo/http_server_demo.h
Normal file
6
sdk/app/http/http_server_demo/http_server_demo.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef HTTP_SERVER_H
|
||||
#define HTTP_SERVER_H
|
||||
|
||||
|
||||
int http_server_init(uint32 ip);
|
||||
#endif
|
||||
153
sdk/app/http/httpfile_client_demo/httpfile_client_demo.c
Normal file
153
sdk/app/http/httpfile_client_demo/httpfile_client_demo.c
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright (c) 2021 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// Example HTTP client. Connect to `s_url`, send request, wait for a response,
|
||||
// print the response and exit.
|
||||
// You can change `s_url` from the command line by executing: ./example YOUR_URL
|
||||
//
|
||||
// To enable SSL/TLS, make SSL=OPENSSL or make SSL=MBEDTLS
|
||||
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "osal/irq.h"
|
||||
#include "osal/work.h"
|
||||
#include "osal/sleep.h"
|
||||
#include "osal/timer.h"
|
||||
#include "hal/gpio.h"
|
||||
#include "lib/common/common.h"
|
||||
#include "lib/common/sysevt.h"
|
||||
#include "lib/syscfg/syscfg.h"
|
||||
#include <string.h>
|
||||
#if HTTPFILE_CLIENT
|
||||
#include "mongoose.h"
|
||||
#include "httpfile_client_demo.h"
|
||||
// The very first web page in history. You can replace it from command line
|
||||
static const char *s_url = "http://192.168.1.100/2.txt";
|
||||
static const char *s_post_data = NULL; // POST data
|
||||
static const uint64_t s_timeout_ms = 1500; // Connect timeout in milliseconds
|
||||
|
||||
static struct mg_str *get_header_value(struct mg_http_message *hm,const char *name);
|
||||
|
||||
// Print HTTP response and signal that we're done
|
||||
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||
if (ev == MG_EV_OPEN) {
|
||||
// Connection created. Store connect expiration time in c->data
|
||||
*(uint64_t *) c->data = mg_millis() + s_timeout_ms;
|
||||
} else if (ev == MG_EV_POLL) {
|
||||
if (mg_millis() > *(uint64_t *) c->data &&
|
||||
(c->is_connecting || c->is_resolving)) {
|
||||
mg_error(c, "Connect timeout");
|
||||
}
|
||||
} else if (ev == MG_EV_CONNECT) {
|
||||
// Connected to server. Extract host name from URL
|
||||
struct mg_str host = mg_url_host(s_url);
|
||||
|
||||
// If s_url is https://, tell client connection to use TLS
|
||||
if (mg_url_is_ssl(s_url)) {
|
||||
struct mg_tls_opts opts = {
|
||||
//.ca = s_ca,
|
||||
.srvname = host
|
||||
};
|
||||
mg_tls_init(c, &opts);
|
||||
}
|
||||
|
||||
// Send request
|
||||
int content_length = s_post_data ? strlen(s_post_data) : 0;
|
||||
mg_printf(c,
|
||||
"%s %s HTTP/1.0\r\n"
|
||||
"Host: %.*s\r\n"
|
||||
"Content-Type: octet-stream\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"\r\n",
|
||||
s_post_data ? "POST" : "GET", mg_url_uri(s_url), (int) host.len,
|
||||
host.ptr, content_length);
|
||||
mg_send(c, s_post_data, content_length);
|
||||
} /**/ else if (ev == MG_EV_HTTP_CHUNK) {
|
||||
//size_t len;
|
||||
//char *data;
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
//fwrite(hm->chunk.ptr, 1, hm->chunk.len, stdout);
|
||||
//MG_INFO(("hm->chunk.len %d %.*s\r\n", (int)hm->chunk.len, (int) hm->chunk.len, hm->chunk.ptr));
|
||||
mg_file_write(&mg_fs_fat, HTTP_DIR"/6.txt", hm->chunk.ptr, hm->chunk.len);
|
||||
mg_http_delete_chunk(c, hm);
|
||||
//data = mg_file_read(&mg_fs_fat,HTTP_DIR"/2.txt",&len);
|
||||
//MG_INFO(("mg_file_read length is %d\r\n",len));
|
||||
if (hm->chunk.len == 0) *(bool *) fn_data = true; // Last chunk
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
// Response is received. Print it
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
get_header_value(hm,"Content-Type");
|
||||
printf("hm->message.len:%d\r\n",hm->message.len);
|
||||
MG_INFO(("%.*s", (int) hm->message.len, hm->message.ptr));
|
||||
c->is_closing = 1; // Tell mongoose to close this connection
|
||||
*(bool *) fn_data = true; // Tell event loop to stop
|
||||
} else if (ev == MG_EV_ERROR) {
|
||||
*(bool *) fn_data = true; // Error, tell event loop to stop
|
||||
}
|
||||
}
|
||||
|
||||
os_task_t httpfile_client_task;
|
||||
|
||||
int httpfile_client_demo(void *arg) {
|
||||
|
||||
struct mg_mgr mgr; // Event manager
|
||||
bool done = false; // Event handler flips it to true
|
||||
int ret;
|
||||
mg_log_set(MG_LL_NONE); // Set to 0 to disable debug
|
||||
mg_mgr_init(&mgr); // Initialise event manager
|
||||
ret = f_mkdir(HTTP_DIR);
|
||||
if(ret != 0 && ret != 8)
|
||||
return -1;
|
||||
mg_http_connect(&mgr, s_url, fn, &done); // Create client connection
|
||||
while (!done) mg_mgr_poll(&mgr, 10); // Event manager loops until 'done'
|
||||
mg_mgr_free(&mgr); // Free resources
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sysevt_hdl_res dhcp_client_get_ip(uint32 event_id, uint32 data, uint32 priv)
|
||||
{
|
||||
static uint8_t is_get_ip = 0;
|
||||
printf("%s:%d!!!!!!!!!!!\n",__FUNCTION__,__LINE__);
|
||||
if(!is_get_ip)
|
||||
{
|
||||
is_get_ip = 1;
|
||||
|
||||
OS_TASK_INIT("httpfile_client_task", &httpfile_client_task, httpfile_client_demo, NULL, OS_TASK_PRIORITY_NORMAL, 20*1024);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int httpfile_client_init(uint32 ip)
|
||||
{
|
||||
|
||||
printf("%s:%d\tip:%s\n",__FUNCTION__,__LINE__,inet_ntoa(ip));
|
||||
|
||||
sys_event_take(SYS_EVENT(SYS_EVENT_WIFI, SYSEVT_WIFI_STA_CONNECTTED),dhcp_client_get_ip,0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mg_str *get_header_value(struct mg_http_message *hm,const char *name) {
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
struct mg_str *cl;
|
||||
if ((cl = mg_http_get_header(hm, name)) != NULL) {
|
||||
printf("%s--get %s %.*s\r\n", __FILE__, name, (int) cl->len, cl->ptr);
|
||||
return cl;
|
||||
} else {
|
||||
printf("%s--can not get %s %.*s\r\n", __FILE__, name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
7
sdk/app/http/httpfile_client_demo/httpfile_client_demo.h
Normal file
7
sdk/app/http/httpfile_client_demo/httpfile_client_demo.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef HTTPFILE_CLIENT_H
|
||||
#define HTTPFILE_CLIENT_H
|
||||
|
||||
#define HTTP_DIR "0:/HTTP"
|
||||
|
||||
int httpfile_client_init(uint32 ip);
|
||||
#endif
|
||||
124
sdk/app/http/httpfile_server_demo/httpfile_server_demo.c
Normal file
124
sdk/app/http/httpfile_server_demo/httpfile_server_demo.c
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (c) 2020 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// HTTP server example. This server serves both static and dynamic content.
|
||||
// It opens two ports: plain HTTP on port 8000 and HTTP on port 8443.
|
||||
// It implements the following endpoints:
|
||||
// /api/stats - respond with free-formatted stats on current connections
|
||||
// /api/f2/:id - wildcard example, respond with JSON string {"result": "URI"}
|
||||
// any other URI serves static files from s_root_dir
|
||||
//
|
||||
// To enable SSL/TLS (using self-signed certificates in PEM files),
|
||||
// 1. make SSL=OPENSSL or make SSL=MBEDTLS
|
||||
// 2. curl -k https://127.0.0.1:8443
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "osal/irq.h"
|
||||
#include "osal/work.h"
|
||||
#include "osal/sleep.h"
|
||||
#include "osal/timer.h"
|
||||
#include "hal/gpio.h"
|
||||
#include "lib/common/common.h"
|
||||
#include "lib/common/sysevt.h"
|
||||
#include "lib/syscfg/syscfg.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "netif/ethernetif.h"
|
||||
#include <string.h>
|
||||
#if HTTPFILE_SERVER
|
||||
#include "mongoose.h"
|
||||
#include "httpfile_server_demo.h"
|
||||
static char s_http_addr[30] = "http://"; // HTTP port
|
||||
os_task_t httpfile_server_task;
|
||||
// HTTP request handler function. It implements the following endpoints:
|
||||
// /upload - Saves the next file chunk
|
||||
// all other URI - serves web_root/ directory
|
||||
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (ev == MG_EV_HTTP_CHUNK && mg_http_match_uri(hm, "/upload")) {
|
||||
//MG_INFO(("Got chunk len %lu , Got query len %lu\r\n", (unsigned long) hm->chunk.len,(unsigned long) hm->query.len));
|
||||
//MG_INFO(("Query string: [%.*s]\r\n", (int) hm->query.len, hm->query.ptr));
|
||||
mg_file_write(&mg_fs_fat, HTTP_DIR"/e17.txt", hm->chunk.ptr, hm->chunk.len);
|
||||
//MG_INFO(("Chunk data: [%.*s]\r\n", (int) hm->chunk.len, hm->chunk.ptr));
|
||||
mg_http_delete_chunk(c, hm);
|
||||
if (hm->chunk.len == 0) {
|
||||
MG_INFO(("Last chunk received, sending response"));
|
||||
mg_http_reply(c, 200, "", "ok (chunked)\n");
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
struct mg_http_serve_opts opts = { .fs = &mg_fs_fat, .root_dir = HTTP_DIR"/web_root"};
|
||||
mg_http_serve_dir(c, hm, &opts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int httpfile_server_demo(void) {
|
||||
struct mg_mgr mgr; // Event manager
|
||||
int ret;
|
||||
mg_log_set(MG_LL_NONE); // Set log level
|
||||
mg_mgr_init(&mgr); // Initialise event manager
|
||||
ret = f_mkdir(HTTP_DIR);
|
||||
if(ret != 0 && ret != 8) {
|
||||
printf("%s set failed\r\n",__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
mg_http_listen(&mgr, s_http_addr, fn, NULL); // Create HTTP listener
|
||||
for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
||||
mg_mgr_free(&mgr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static sysevt_hdl_res dhcp_client_get_ip(uint32 event_id, uint32 data, uint32 priv)
|
||||
{
|
||||
static uint8_t is_get_ip = 0;
|
||||
printf("%s:%d!!!!!!!!!!!\n",__FUNCTION__,__LINE__);
|
||||
if(!is_get_ip)
|
||||
{
|
||||
ip_addr_t ipaddr;
|
||||
char *ip;
|
||||
is_get_ip = 1;
|
||||
ipaddr = lwip_netif_get_ip2("w0");
|
||||
ip = inet_ntoa(ipaddr);
|
||||
strncat(s_http_addr,ip,strlen(ip));
|
||||
printf("server_ip: %s\r\n", s_http_addr);
|
||||
|
||||
OS_TASK_INIT("http", &httpfile_server_task, httpfile_server_demo, NULL, OS_TASK_PRIORITY_NORMAL, 30*1024);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int httpfile_server_init(uint32 ip)
|
||||
{
|
||||
|
||||
printf("%s:%d\tip:%X\n",__FUNCTION__,__LINE__,ip);
|
||||
|
||||
|
||||
if(!ip)
|
||||
{
|
||||
sys_event_take(SYS_EVENT(SYS_EVENT_NETWORK, SYSEVT_LWIP_DHCPC_DONE),dhcp_client_get_ip,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ip_addr_t ipaddr;
|
||||
char *ip;
|
||||
ipaddr = lwip_netif_get_ip2("w0");
|
||||
ip = inet_ntoa(ipaddr);
|
||||
strncat(s_http_addr,ip,strlen(ip));
|
||||
printf("server_ip: %s\r\n", s_http_addr);
|
||||
OS_TASK_INIT("http", &httpfile_server_task, httpfile_server_demo, NULL, OS_TASK_PRIORITY_NORMAL, 30*1024);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
7
sdk/app/http/httpfile_server_demo/httpfile_server_demo.h
Normal file
7
sdk/app/http/httpfile_server_demo/httpfile_server_demo.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef HTTPFILE_SERVER_H
|
||||
#define HTTPFILE_SERVER_H
|
||||
|
||||
#define HTTP_DIR "0:/HTTP"
|
||||
|
||||
int httpfile_server_init(uint32 ip);
|
||||
#endif
|
||||
1702
sdk/app/intercom/intercom.c
Normal file
1702
sdk/app/intercom/intercom.c
Normal file
File diff suppressed because it is too large
Load Diff
155
sdk/app/intercom/intercom.h
Normal file
155
sdk/app/intercom/intercom.h
Normal file
@@ -0,0 +1,155 @@
|
||||
#ifndef _INTERCOM_H_
|
||||
#define _INTERCOM_H_
|
||||
|
||||
#include "basic_include.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/audio/ring_buffer/ring_buffer.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "keyWork.h"
|
||||
#include "keyScan.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define INTERCOM_MALLOC av_psram_malloc
|
||||
#define INTERCOM_ZALLOC av_psram_zalloc
|
||||
#define INTERCOM_FREE av_psram_free
|
||||
#else
|
||||
#define INTERCOM_MALLOC av_malloc
|
||||
#define INTERCOM_ZALLOC av_zalloc
|
||||
#define INTERCOM_FREE av_free
|
||||
#endif
|
||||
|
||||
#define ADJUST_BY_LOSS 1
|
||||
#define ADJUST_BY_MCS 2
|
||||
|
||||
|
||||
enum {
|
||||
intercom_live_audio = 1,
|
||||
intercom_playback_audio,
|
||||
};
|
||||
|
||||
enum {
|
||||
high_bitrate_mode,
|
||||
low_bitrate_mode,
|
||||
};
|
||||
|
||||
enum {
|
||||
mild_loss,
|
||||
serious_loss,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct list_head list;
|
||||
uint8_t *buf_addr;
|
||||
}audio_node;
|
||||
|
||||
typedef struct {
|
||||
struct list_head list;
|
||||
struct list_head node_head;
|
||||
uint8_t seq;
|
||||
uint8_t type; //1:实时流,2:回放流
|
||||
uint16_t sort;
|
||||
uint32_t timestamp;
|
||||
uint32_t code_len;
|
||||
uint32_t identify_num;
|
||||
uint32_t node_cnt;
|
||||
} __attribute__((packed)) sublist;
|
||||
|
||||
typedef struct {
|
||||
struct list_head list;
|
||||
uint8_t* buf_addr;
|
||||
uint32_t data_len;
|
||||
}ringbuf_manage;
|
||||
|
||||
typedef enum {
|
||||
SEND_ONLY,
|
||||
RECV_ONLY,
|
||||
NORMAL_MODE,
|
||||
}transfer_mode;
|
||||
|
||||
typedef enum {
|
||||
intercom_run,
|
||||
intercom_stop,
|
||||
}intercom_state;
|
||||
|
||||
typedef struct {
|
||||
uint8_t run_state;
|
||||
uint8_t run_task;
|
||||
uint8_t recv_stream_type;
|
||||
uint8_t send_stream_type;
|
||||
|
||||
uint8_t cur_bitrate_mode;
|
||||
uint8_t new_bitrate_mode;
|
||||
uint8_t loss_state;
|
||||
|
||||
uint8_t connected_num;
|
||||
uint8_t current_dev_id;
|
||||
uint8_t next_dev_id;
|
||||
|
||||
int local_trans_fd;
|
||||
int local_ret_fd;
|
||||
|
||||
struct sockaddr_in local_trans_addr;
|
||||
struct sockaddr_in local_ret_addr;
|
||||
struct sockaddr_in remote_trans_addr;
|
||||
struct sockaddr_in remote_ret_addr;
|
||||
|
||||
void *init_task_hdl;
|
||||
void *recv_task_hdl;
|
||||
void *send_task_hdl;
|
||||
void *output_task_hdl;
|
||||
|
||||
uint8_t *recv_buf;
|
||||
uint8_t *send_buf;
|
||||
uint8_t *sort_buf;
|
||||
RINGBUF *encoded_ringbuf;
|
||||
ringbuf_manage *ringbuf_manage_src;
|
||||
audio_node *audio_node_src;
|
||||
sublist *sublist_src;
|
||||
|
||||
struct list_head checkList_head;
|
||||
struct list_head useList_head;
|
||||
struct list_head nodeList_head;
|
||||
struct list_head sublist_head;
|
||||
struct list_head ringbuf_manage_empty;
|
||||
struct list_head ringbuf_manage_used;
|
||||
struct list_head *manage_cur_push;
|
||||
struct list_head *manage_cur_pop;
|
||||
|
||||
struct list_head device_head;
|
||||
|
||||
struct msi *msi;
|
||||
struct msi *magic_voice_msi;
|
||||
struct msi *encoder_msi;
|
||||
struct msi *decoder_msi;
|
||||
struct fbpool tx_pool;
|
||||
|
||||
struct os_mutex state_mutex;
|
||||
struct os_mutex list_mutex;
|
||||
struct os_mutex send_mutex;
|
||||
struct os_event clear_event;
|
||||
struct os_semaphore output_sema;
|
||||
struct os_timer ctl_timer;
|
||||
} INTERCOM_STRUCT;
|
||||
|
||||
typedef struct {
|
||||
struct list_head list;
|
||||
uint32_t ip_addr;
|
||||
uint32_t identify_num;
|
||||
uint8_t dev_id;
|
||||
uint8_t online;
|
||||
uint16_t timeout_cnt;
|
||||
} intercom_device;
|
||||
|
||||
struct msi *intercom_init(void);
|
||||
void intercom_deinit(void);
|
||||
void intercom_send_enable(uint8_t state);
|
||||
void intercom_recv_enable(uint8_t state);
|
||||
void intercom_encode_pause(uint8_t state, uint8_t clear);
|
||||
void intercom_decode_pause(uint8_t state, uint8_t clear);
|
||||
void intercom_reset_play(void);
|
||||
void intercom_set_stream_type(uint8_t recv_type, uint8_t send_type);
|
||||
uint32_t intercom_ctrl_key(struct key_callback_list_s *callback_list,uint32_t keyvalue,uint32_t extern_value);
|
||||
#endif
|
||||
155
sdk/app/interface_management/interface_mgnt_msi.c
Normal file
155
sdk/app/interface_management/interface_mgnt_msi.c
Normal file
@@ -0,0 +1,155 @@
|
||||
#include "basic_include.h"
|
||||
#include "stream_define.h"
|
||||
#include "lv_demo_benchmark.h"
|
||||
#include "keyWork.h"
|
||||
#include "keyScan.h"
|
||||
#include "lvgl/lvgl.h"
|
||||
#include "ui/main_ui.h"
|
||||
void lv_port_disp_init_msi(const char *name,uint16_t w,uint16_t h,uint8_t rotate);
|
||||
void lv_port_indev_init(void);
|
||||
lv_style_t g_style;
|
||||
|
||||
#if KEY_MODULE_EN == 1
|
||||
typedef uint32_t (*lvgl_get_key)(uint32_t key);
|
||||
static struct os_msgqueue lvgl_key_msgq;
|
||||
static lvgl_get_key g_lvgl_get_key = NULL;
|
||||
#endif
|
||||
|
||||
void set_lvgl_get_key_func(void *func)
|
||||
{
|
||||
#if KEY_MODULE_EN == 1
|
||||
g_lvgl_get_key = (lvgl_get_key)func;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t key_get_data()
|
||||
{
|
||||
uint32_t key_ret = 0;
|
||||
#if KEY_MODULE_EN == 1
|
||||
static uint32_t last_key = 0xff;
|
||||
uint32_t val = os_msgq_get(&lvgl_key_msgq,0);
|
||||
//如果有按键被按下,就进入判断
|
||||
//如果没有按键按下,就判断一下上一次是否为释放按键,如果不是,就执行上一次按键的键值(有可能是长按之类)
|
||||
if(g_lvgl_get_key)
|
||||
{
|
||||
if(val > 0)
|
||||
{
|
||||
return g_lvgl_get_key(val);
|
||||
}
|
||||
return key_ret;
|
||||
}
|
||||
if(val > 0 || !(((last_key&0xff) == KEY_EVENT_SUP) || ((last_key&0xff) == KEY_EVENT_LUP)))
|
||||
{
|
||||
if(!(val>0))
|
||||
{
|
||||
val = last_key;
|
||||
}
|
||||
last_key = val;
|
||||
if((val&0xff) == KEY_EVENT_SUP)
|
||||
{
|
||||
switch(val>>8)
|
||||
{
|
||||
case AD_UP:
|
||||
key_ret = LV_KEY_PREV;
|
||||
break;
|
||||
case AD_DOWN:
|
||||
key_ret = LV_KEY_NEXT;
|
||||
break;
|
||||
case AD_LEFT:
|
||||
key_ret = LV_KEY_PREV;
|
||||
break;
|
||||
case AD_RIGHT:
|
||||
key_ret = LV_KEY_NEXT;
|
||||
break;
|
||||
case AD_PRESS:
|
||||
key_ret = LV_KEY_ENTER;
|
||||
break;
|
||||
case AD_A:
|
||||
break;
|
||||
case AD_B:
|
||||
break;
|
||||
case AD_C:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if((val&0xff) == KEY_EVENT_REPEAT)
|
||||
{
|
||||
|
||||
switch(val>>8)
|
||||
{
|
||||
//lvgl需要持续按键才能识别长按
|
||||
case AD_PRESS:
|
||||
key_ret = LV_KEY_ENTER;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return key_ret;
|
||||
}
|
||||
|
||||
#if KEY_MODULE_EN == 1
|
||||
uint32_t lvgl_push_key(struct key_callback_list_s *callback_list,uint32_t keyvalue,uint32_t extern_value)
|
||||
{
|
||||
os_msgq_put(&lvgl_key_msgq,keyvalue,0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void lvgl_run_msi(void *d){
|
||||
uint32 cur_tick;
|
||||
cur_tick = os_jiffies();
|
||||
while(1){
|
||||
os_sleep_ms(1);
|
||||
lv_tick_inc(os_jiffies()-cur_tick);
|
||||
cur_tick = os_jiffies();
|
||||
lv_timer_handler();
|
||||
if(os_jiffies()-cur_tick > 30)
|
||||
{
|
||||
os_printf("%s:%d\tuse_time:%d\n",__FUNCTION__,__LINE__,os_jiffies()-cur_tick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lvgl_init_msi(uint16_t w,uint16_t h,uint8_t rotate)
|
||||
{
|
||||
#if KEY_MODULE_EN == 1
|
||||
memset(&lvgl_key_msgq,0,sizeof(lvgl_key_msgq));
|
||||
os_msgq_init(&lvgl_key_msgq,10);
|
||||
add_keycallback(lvgl_push_key,NULL);
|
||||
#endif
|
||||
os_printf("w:%d h:%d rotate:%d\n",w,h,rotate);
|
||||
lv_init(); // lvgl初始化,如果这个没有初始化,那么下面的初始化会崩溃
|
||||
lv_port_disp_init_msi(S_LVGL_OSD,w,h,rotate); // 显示器初始化
|
||||
lv_port_indev_init();
|
||||
|
||||
lv_style_reset(&g_style);
|
||||
lv_style_init(&g_style);
|
||||
lv_style_set_bg_color(&g_style, lv_color_make(0x00, 0x00, 0x00));
|
||||
lv_style_set_shadow_color(&g_style, lv_color_make(0x00, 0x00, 0x00));
|
||||
lv_style_set_border_color(&g_style, lv_color_make(0x00, 0x00, 0x00));
|
||||
lv_style_set_outline_color(&g_style, lv_color_make(0x00, 0x00, 0x00));
|
||||
lv_style_set_radius(&g_style, 0);
|
||||
|
||||
// lv_demo_benchmark(1);
|
||||
|
||||
#ifdef SYS_APP_WALKIE_TALKIE
|
||||
void walkie_talkie_demo(void);
|
||||
walkie_talkie_demo();
|
||||
#else
|
||||
main_ui(NULL);
|
||||
#endif
|
||||
|
||||
os_task_create("gui_thread", lvgl_run_msi, NULL, OS_TASK_PRIORITY_ABOVE_NORMAL, 0, NULL, 4096);
|
||||
|
||||
}
|
||||
|
||||
|
||||
87
sdk/app/jpgdef.h
Normal file
87
sdk/app/jpgdef.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#ifndef __JPGDEF_H
|
||||
#define __JPGDEF_H
|
||||
|
||||
#include "sys_config.h"
|
||||
|
||||
struct stream_jpeg_data_s
|
||||
{
|
||||
struct stream_jpeg_data_s *next;
|
||||
void *data;
|
||||
int ref;
|
||||
};
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
CUSTOM_GET_NODE_LEN,
|
||||
CUSTOM_GET_NODE_BUF,
|
||||
CUSTOM_GET_FIRST_BUF,
|
||||
CUSTOM_FREE_NODE,
|
||||
CUSTOM_DEL_NODE,
|
||||
CUSTOM_GET_NODE_COUNT,
|
||||
};
|
||||
|
||||
typedef int (*commom_free_node)(void *get_f);
|
||||
typedef unsigned int (*commom_len)(void *get_f);
|
||||
typedef unsigned int (*commom_node_len)(void *get_f);
|
||||
typedef void *(*commom_buf)(void *get_f);
|
||||
typedef void (*commom_del)(void *get_f);
|
||||
typedef unsigned int (*commom_get_time)(void *get_f);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
commom_free_node free_node;
|
||||
commom_node_len get_node_len;
|
||||
commom_len get_len;
|
||||
commom_buf get_buf;
|
||||
commom_del del;
|
||||
commom_get_time get_time;
|
||||
|
||||
}common_ops_s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *priv1,*priv2;//为了兼容jpg.c的frame结构体(struct list_head list),所以去除前面的8字节,后面usb一样
|
||||
//注册一个通用的结构体,作为操作帧,通用形(这里用void指针,到.c后赋值一个实体)
|
||||
common_ops_s *common_ops;
|
||||
}common_s;
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
#include "stream_frame.h"
|
||||
//兼容旧版本一些接口,后续可能会移除
|
||||
#define GET_FRAME(f) recv_real_data(f)
|
||||
#define GET_DATA_LEN(f) (uint32_t) get_stream_real_data_len(f)
|
||||
#define GET_DATA_TIMESTAMP(f) (uint32_t) get_stream_data_timestamp(f)
|
||||
#define GET_NODE_LEN(f) (uint32_t) stream_data_custom_cmd_func(f,CUSTOM_GET_NODE_LEN,NULL)
|
||||
#define FREE_JPG_NODE(f) (uint32_t) stream_data_custom_cmd_func(f,CUSTOM_FREE_NODE,NULL)
|
||||
#define GET_JPG_BUF(f) (uint32_t) stream_data_custom_cmd_func(f,CUSTOM_GET_FIRST_BUF,NULL)
|
||||
#define DEL_JPG_FRAME(f) free_data(f)
|
||||
#define DEL_JPEG_NODE(f,d) (uint32_t) stream_data_custom_cmd_func(f,CUSTOM_DEL_NODE,d)
|
||||
#define GET_DATA_BUF(f) (uint32_t) get_stream_real_data(f)
|
||||
#define DEL_FRAME(f) free_data(f)
|
||||
#define GET_JPG_SELF_BUF(f,d) (uint32_t) stream_data_custom_cmd_func(f,CUSTOM_GET_NODE_BUF,d)
|
||||
|
||||
#define GET_NODE_COUNT(f) (uint32_t) stream_data_custom_cmd_func(f,CUSTOM_GET_NODE_COUNT,NULL)
|
||||
#define UVC_HEAD_RESERVER 24 //每段JPEG BUF前面预留用于填充其他数据的数据量,无需预留填0
|
||||
void *get_jpeg_first_buf(void *d);
|
||||
void del_jpeg_first_node(void *d);
|
||||
void del_jpeg_frame(void *d);
|
||||
struct list_head* get_frame(uint8 jpgid);
|
||||
uint32 get_jpeg_len(void *d);
|
||||
#else
|
||||
#include "stream_frame.h"
|
||||
#include "basic_include.h"
|
||||
#include "lib/multimedia/msi.h"
|
||||
#define DEL_JPG_FRAME(f) msi_delete_fb(NULL,(struct framebuff *)f)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
465
sdk/app/loop_record_moudle/loop_record_moudle.c
Normal file
465
sdk/app/loop_record_moudle/loop_record_moudle.c
Normal file
@@ -0,0 +1,465 @@
|
||||
#include "fatfs/osal_file.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
#include "typesdef.h"
|
||||
#include "utlist.h"
|
||||
#include "loop_record_moudle/loop_record_moudle.h"
|
||||
|
||||
// 结构体申请空间函数
|
||||
#define STREAM_MALLOC av_psram_malloc
|
||||
#define STREAM_FREE av_psram_free
|
||||
#define STREAM_ZALLOC av_psram_zalloc
|
||||
|
||||
typedef struct Node {
|
||||
int value;
|
||||
struct Node *next;
|
||||
} Node;
|
||||
|
||||
typedef struct {
|
||||
Node *head;
|
||||
Node *tail;
|
||||
size_t size;
|
||||
} LinkedList;
|
||||
|
||||
typedef struct el
|
||||
{
|
||||
struct el *next, *prev;
|
||||
uint32_t filesize;
|
||||
char filename[32];
|
||||
} el;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
el *head;
|
||||
char dir_path[32];
|
||||
LinkedList *list; // 存放异常文件夹
|
||||
} loop_file;
|
||||
|
||||
// 默认当作后缀名是4位,这个应该是用户去考虑的
|
||||
// 主要用于排序
|
||||
static uint8_t file_cmp(char *dir1, char *dir2)
|
||||
{
|
||||
int compare = 0;
|
||||
compare = os_strcmp(dir1, dir2);
|
||||
if(compare < 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int namecmp(el *a, el *b)
|
||||
{
|
||||
return file_cmp(a->filename, b->filename);
|
||||
}
|
||||
|
||||
static loop_file *loop_get_file_init()
|
||||
{
|
||||
loop_file *loop = (loop_file *) STREAM_ZALLOC(sizeof(loop_file));
|
||||
return loop;
|
||||
}
|
||||
|
||||
static void loop_get_file_deinit(void *loop_f)
|
||||
{
|
||||
loop_file *loop = (loop_file *) loop_f;
|
||||
if (loop)
|
||||
{
|
||||
el *el, *tmp;
|
||||
LL_FOREACH_SAFE(loop->head, el, tmp)
|
||||
{
|
||||
DL_DELETE(loop->head, el);
|
||||
STREAM_FREE(el);
|
||||
}
|
||||
STREAM_FREE(loop);
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t loop_add_file(void *loop_f, char *file_name, int filesize)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
loop_file *loop = (loop_file *) loop_f;
|
||||
if (loop)
|
||||
{
|
||||
el *node = (el *) STREAM_MALLOC(sizeof(el));
|
||||
if (node)
|
||||
{
|
||||
node->filesize = filesize;
|
||||
strcpy(node->filename, file_name);
|
||||
DL_APPEND(loop->head, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = RET_ERR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = RET_ERR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int8_t loop_add_file_sort(void *loop_f)
|
||||
{
|
||||
loop_file *loop = (loop_file *) loop_f;
|
||||
if (loop)
|
||||
{
|
||||
DL_SORT(loop->head, namecmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_list(LinkedList *list)
|
||||
{
|
||||
list->head = list->tail = NULL;
|
||||
list->size = 0;
|
||||
}
|
||||
|
||||
void push_back(LinkedList *list, uint32_t value)
|
||||
{
|
||||
Node *node = STREAM_MALLOC(sizeof(Node));
|
||||
if (!node) return;
|
||||
node->value = value;
|
||||
node->next = NULL;
|
||||
|
||||
if (list->tail) {
|
||||
list->tail->next = node;
|
||||
} else {
|
||||
list->head = node;
|
||||
}
|
||||
list->tail = node;
|
||||
list->size++;
|
||||
}
|
||||
|
||||
void free_list(void *loop_f)
|
||||
{
|
||||
loop_file *loop = (loop_file *) loop_f;
|
||||
LinkedList *list = (LinkedList *) loop->list;
|
||||
if(list)
|
||||
{
|
||||
Node *cur = list->head;
|
||||
while (cur) {
|
||||
Node *next = cur->next;
|
||||
STREAM_FREE(cur);
|
||||
cur = next;
|
||||
}
|
||||
list->head = list->tail = NULL;
|
||||
list->size = 0;
|
||||
STREAM_FREE(list);
|
||||
loop->list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void* get_err_dir_list(void *loop_f)
|
||||
{
|
||||
loop_file *loop = (loop_file *) loop_f;
|
||||
return loop->list;
|
||||
}
|
||||
|
||||
void err_dir_add_list(void *loop_f, const char *dir_path)
|
||||
{
|
||||
loop_file *loop = (loop_file *) loop_f;
|
||||
LinkedList *list = NULL;
|
||||
|
||||
if(loop->list)
|
||||
{
|
||||
list = (LinkedList *) loop->list;
|
||||
}
|
||||
else
|
||||
{
|
||||
list = (LinkedList *)STREAM_MALLOC(sizeof(LinkedList));
|
||||
if(list)
|
||||
{
|
||||
loop->list = list;
|
||||
init_list(list);
|
||||
}
|
||||
else
|
||||
{
|
||||
_os_printf("malloc err list failed\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const char *last_slash = strrchr(dir_path, '/');
|
||||
const char *num_ptr = (last_slash != NULL) ? (last_slash + 1) : dir_path;
|
||||
char *endptr;
|
||||
uint32_t value = strtoul(num_ptr, &endptr, 10);
|
||||
|
||||
if (endptr == num_ptr || (*endptr != '\0')) {
|
||||
_os_printf("Error: '%s' is not a valid number directory\r\n", num_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if(value > 0)
|
||||
{
|
||||
Node *cur = list->head;
|
||||
while (cur) {
|
||||
if (cur->value == value) {
|
||||
_os_printf("dir %s is exist\r\n");
|
||||
return;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
push_back(list, value);
|
||||
_os_printf("add %s to err dir list\r\n", dir_path);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t find_dir_with_min_number(const char *path, char* result_name, LinkedList *list)
|
||||
{
|
||||
void *dir;
|
||||
FILINFO *fil;
|
||||
uint32_t min_number = 0xFFFFFFFF;
|
||||
char min_dir_name[32];
|
||||
uint8_t err_dir = 0;
|
||||
|
||||
dir = osal_opendir(path);
|
||||
if(dir == NULL) {
|
||||
os_printf("open dir failed, dir: %s\r\n", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
fil = osal_readdir(dir);
|
||||
|
||||
if(fil == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(fil->fname[0] == '.')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (osal_dirent_isdir(fil))
|
||||
{
|
||||
char *dir_name = fil->fname;
|
||||
uint32_t current_number = 0;
|
||||
int found_digit = 0;
|
||||
|
||||
for (int i = 0; dir_name[i] != '\0'; i++) {
|
||||
if (dir_name[i] >= '0' && dir_name[i] <= '9') {
|
||||
current_number = current_number * 10 + (dir_name[i] - '0');
|
||||
} else {
|
||||
found_digit = 0;
|
||||
break;
|
||||
}
|
||||
found_digit = 1;
|
||||
}
|
||||
|
||||
if (found_digit) {
|
||||
if(list)
|
||||
{
|
||||
Node *cur = list->head;
|
||||
while (cur) {
|
||||
if (cur->value == current_number) {
|
||||
err_dir = 1;
|
||||
break;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
if (current_number < min_number && !err_dir) {
|
||||
min_number = current_number;
|
||||
os_strcpy(min_dir_name, dir_name);
|
||||
}
|
||||
err_dir = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
osal_closedir(dir);
|
||||
|
||||
if (min_number != 0xFFFFFFFF) {
|
||||
strcpy(result_name, min_dir_name);
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_file(void *loop_f, const char *path, const char *extension_name)
|
||||
{
|
||||
loop_file *loop = (loop_file *) loop_f;
|
||||
void *dir;
|
||||
FILINFO *fil;
|
||||
FRESULT res = 0;
|
||||
uint8_t extension_name_len = strlen(extension_name);
|
||||
|
||||
dir = osal_opendir(path);
|
||||
if (!dir)
|
||||
{
|
||||
os_printf("get_dir res: %d\n", res);
|
||||
return;
|
||||
}
|
||||
do
|
||||
{
|
||||
// dent = VFS_readdir(dir);
|
||||
fil = osal_readdir(dir);
|
||||
if (fil)
|
||||
{
|
||||
if (osal_dirent_isdir(fil))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fil->fattrib & AM_RDO) {
|
||||
os_printf("File is read-only\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查后缀名是否匹配
|
||||
uint8_t extension_filename[16]; // 文件后缀名转换,统一大写
|
||||
|
||||
char *fname = osal_dirent_name(fil);
|
||||
uint8_t filename_len = strlen(fname);
|
||||
uint32_t filesize = osal_dirent_size(fil);
|
||||
|
||||
if (filename_len - extension_name_len > 0)
|
||||
{
|
||||
// 转换成大写
|
||||
for (uint8_t i = 0; i < extension_name_len; i++)
|
||||
{
|
||||
extension_filename[i] = toupper(fname[filename_len - extension_name_len + i]);
|
||||
}
|
||||
// 后缀名匹配
|
||||
if (memcmp(extension_name, extension_filename, extension_name_len) == 0)
|
||||
{
|
||||
el *name = (el *) STREAM_MALLOC(sizeof(el));
|
||||
name->filesize = filesize;
|
||||
os_strncpy(name->filename, fname, sizeof(name->filename));
|
||||
DL_APPEND(loop->head, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (fil);
|
||||
osal_closedir(dir);
|
||||
}
|
||||
|
||||
// 读取文件夹列表
|
||||
void *get_file_list(const char *rec_path, const char *extension_name)
|
||||
{
|
||||
char dir_path[32];
|
||||
char min_dir_name[32];
|
||||
|
||||
if(find_dir_with_min_number(rec_path, min_dir_name, NULL))
|
||||
{
|
||||
os_printf("fine dir error, path: %s\r\n", rec_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_sprintf(dir_path, "%s/%s", rec_path, min_dir_name);
|
||||
loop_file *loop = loop_get_file_init();
|
||||
if (loop)
|
||||
{
|
||||
loop->list = NULL;
|
||||
os_strcpy(loop->dir_path, dir_path);
|
||||
get_file(loop, dir_path, extension_name);
|
||||
// 排序
|
||||
loop_add_file_sort(loop);
|
||||
}
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
void *get_file_list2(const char *rec_path, const char *extension_name, void *list)
|
||||
{
|
||||
char dir_path[32];
|
||||
char min_dir_name[32];
|
||||
|
||||
if(find_dir_with_min_number(rec_path, min_dir_name, list))
|
||||
{
|
||||
os_printf("fine dir error, path: %s\r\n", rec_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os_sprintf(dir_path, "%s/%s", rec_path, min_dir_name);
|
||||
loop_file *loop = loop_get_file_init();
|
||||
if (loop)
|
||||
{
|
||||
loop->list = list;
|
||||
os_strcpy(loop->dir_path, dir_path);
|
||||
get_file(loop, dir_path, extension_name);
|
||||
// 排序
|
||||
loop_add_file_sort(loop);
|
||||
}
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
void free_file_list(void *loop_f)
|
||||
{
|
||||
loop_get_file_deinit(loop_f);
|
||||
}
|
||||
|
||||
void *get_file_node(void *loop_f)
|
||||
{
|
||||
el *el = NULL, *tmp;
|
||||
loop_file *loop = (loop_file *) loop_f;
|
||||
if (loop)
|
||||
{
|
||||
LL_FOREACH_SAFE(loop->head, el, tmp)
|
||||
{
|
||||
DL_DELETE(loop->head, el);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
void free_file_node(void *node)
|
||||
{
|
||||
el *file_node = (el *) node;
|
||||
if (file_node)
|
||||
{
|
||||
STREAM_FREE(file_node);
|
||||
}
|
||||
}
|
||||
|
||||
char *get_file_name(void *node)
|
||||
{
|
||||
el *file_node = (el *) node;
|
||||
if (file_node)
|
||||
{
|
||||
return file_node->filename;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t get_file_size(void *node)
|
||||
{
|
||||
el *file_node = (el *) node;
|
||||
if (file_node)
|
||||
{
|
||||
return file_node->filesize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *get_file_dir(void *loop_f)
|
||||
{
|
||||
loop_file *loop = (loop_file *) loop_f;
|
||||
if (loop)
|
||||
{
|
||||
if(loop->dir_path)
|
||||
{
|
||||
return loop->dir_path;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *get_min_file(void *loop_f)
|
||||
{
|
||||
el *el = NULL, *tmp;
|
||||
loop_file *loop = (loop_file *) loop_f;
|
||||
if (loop)
|
||||
{
|
||||
LL_FOREACH_SAFE(loop->head, el, tmp)
|
||||
{
|
||||
return el->filename;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
19
sdk/app/loop_record_moudle/loop_record_moudle.h
Normal file
19
sdk/app/loop_record_moudle/loop_record_moudle.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef _LOOP_RECORD_MOUDLE_H_
|
||||
#define _LOOP_RECORD_MOUDLE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void free_list(void *loop_f);
|
||||
void* get_err_dir_list(void *loop_f);
|
||||
void err_dir_add_list(void *loop_f, const char *dir_name);
|
||||
void *get_file_list(const char *rec_path, const char *extension_name);
|
||||
void *get_file_list2(const char *rec_path, const char *extension_name, void *list);
|
||||
void free_file_list(void *loop_f);
|
||||
void *get_file_node(void *loop_f);
|
||||
void free_file_node(void *node);
|
||||
char *get_file_name(void *node);
|
||||
uint32_t get_file_size(void *node);
|
||||
void *get_file_dir(void *loop_f);
|
||||
void *get_min_file(void *loop_f);
|
||||
|
||||
#endif
|
||||
1076
sdk/app/loop_record_moudle/utlist.h
Normal file
1076
sdk/app/loop_record_moudle/utlist.h
Normal file
File diff suppressed because it is too large
Load Diff
271
sdk/app/magic_voice/magic_voice.c
Normal file
271
sdk/app/magic_voice/magic_voice.c
Normal file
@@ -0,0 +1,271 @@
|
||||
#include "basic_include.h"
|
||||
#include "autpc_msi.h"
|
||||
#include "magic_voice.h"
|
||||
|
||||
#define MAX_MAGIC_VOICE_RXBUF 1
|
||||
#define MAX_MAGIC_VOICE_TXBUF 1
|
||||
|
||||
#define SETW32TOW16(a) (a>32767)?32767:(a<-32768)?-32768:a
|
||||
|
||||
static const uint8_t delaySamples_table[500] = {
|
||||
0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
|
||||
0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
|
||||
0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
|
||||
0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
|
||||
0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1a,
|
||||
0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,
|
||||
0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1e,0x1e,
|
||||
0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x22,0x22,0x22,0x22,0x22,0x22,
|
||||
0x22,0x22,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x25,0x25,
|
||||
0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x27,0x27,0x27,0x27,0x27,
|
||||
0x27,0x27,0x27,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x2a,0x2a,
|
||||
0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,
|
||||
0x2c,0x2c,0x2c,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2f,
|
||||
0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x31,0x31,
|
||||
0x31,0x31,0x31,0x31,0x31,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x33,0x33,0x33,0x33,0x33,0x33,
|
||||
0x33,0x33,0x33,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x35,0x35,0x35,0x35,0x35,0x35,0x35,
|
||||
0x35,0x35,0x35,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x37,0x37,0x37,0x37,0x37,
|
||||
0x37,0x37,0x37,0x37,0x37,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x39,0x39,
|
||||
0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,
|
||||
0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,
|
||||
0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,
|
||||
0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,
|
||||
0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c
|
||||
};
|
||||
|
||||
static int32_t magic_voice_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
|
||||
{
|
||||
int32_t ret = RET_OK;
|
||||
magic_voice_struct *magic_voice_s = (magic_voice_struct*)msi->priv;
|
||||
switch(cmd_id) {
|
||||
case MSI_CMD_TRANS_FB:
|
||||
{
|
||||
struct framebuff *recv_frame_buf = (struct framebuff *)param1;
|
||||
struct framebuff *send_frame_buf = NULL;
|
||||
if(recv_frame_buf->mtype == F_AUDIO) {
|
||||
if(magic_voice_s->current_type != magic_voice_s->new_type) {
|
||||
uint32_t pitch = 100;
|
||||
switch(magic_voice_s->new_type) {
|
||||
case original_voice: pitch = 100; break;
|
||||
case alien_voice: pitch = 130; break;
|
||||
case robot_voice: pitch = 90; break;
|
||||
case hight_voice: pitch = 150; break;
|
||||
case deep_voice: pitch = 70; break;
|
||||
case etourdi_voice: pitch = 120; break;
|
||||
default: break;
|
||||
}
|
||||
msi_output_cmd(msi, MSI_CMD_AUTPC, MSI_AUTPC_SET_PITCH, pitch);
|
||||
magic_voice_s->current_type = magic_voice_s->new_type;
|
||||
}
|
||||
}
|
||||
if(recv_frame_buf->mtype == F_AUDIO) {
|
||||
uint8_t delaySamples = 0;
|
||||
int16_t *send_buf = NULL;
|
||||
int32_t temp32 = 0;
|
||||
uint32_t nsamples = recv_frame_buf->len / 2;
|
||||
while(!send_frame_buf) {
|
||||
send_frame_buf = fbpool_get(&magic_voice_s->tx_pool, 0, magic_voice_s->msi);
|
||||
if(!send_frame_buf)
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
send_frame_buf->data = (uint8_t*)MAGIC_VOICE_MALLOC(sizeof(int16_t) * nsamples);
|
||||
if(send_frame_buf->data == NULL) {
|
||||
os_printf("magic voice msi malloc send_frame_buf->data fail\n");
|
||||
msi_delete_fb(magic_voice_s->msi, send_frame_buf);
|
||||
break;
|
||||
}
|
||||
if(nsamples != 160) {
|
||||
os_memcpy(send_frame_buf->data, recv_frame_buf->data, recv_frame_buf->len);
|
||||
os_printf("magic voice nsamples abormal\n");
|
||||
goto magic_voice_output;
|
||||
}
|
||||
send_buf = (int16_t*)(send_frame_buf->data);
|
||||
os_memcpy(magic_voice_s->buf+nsamples, recv_frame_buf->data, recv_frame_buf->len);
|
||||
if(magic_voice_s->current_type == alien_voice) {
|
||||
for(uint32_t i=0; i<nsamples; i++) {
|
||||
if(magic_voice_s->table_index < 500)
|
||||
delaySamples = delaySamples_table[magic_voice_s->table_index];
|
||||
else
|
||||
delaySamples = delaySamples_table[999-magic_voice_s->table_index];
|
||||
temp32 = (magic_voice_s->buf[(i + nsamples - delaySamples)]+magic_voice_s->buf[(i + nsamples)])>>1;
|
||||
send_buf[i] = SETW32TOW16(temp32);
|
||||
magic_voice_s->table_index = (magic_voice_s->table_index+1)%1000;
|
||||
}
|
||||
os_memcpy(magic_voice_s->buf,magic_voice_s->buf+nsamples,recv_frame_buf->len);
|
||||
}
|
||||
else if(magic_voice_s->current_type == robot_voice) {
|
||||
int16_t delay_data = 0;
|
||||
int16_t back_data = 0;
|
||||
delaySamples=80;
|
||||
for(uint32_t i=0; i<nsamples; i++) {
|
||||
delay_data = magic_voice_s->buf[(i + nsamples - delaySamples)];
|
||||
back_data = delay_data;
|
||||
temp32 = ((magic_voice_s->buf[nsamples+i]>>1)+delay_data)*8/10;
|
||||
send_buf[i] = SETW32TOW16(temp32);
|
||||
temp32 = ((magic_voice_s->buf[nsamples+i]>>1)+(back_data<<2)/5);
|
||||
magic_voice_s->buf[nsamples+i] = SETW32TOW16(temp32);
|
||||
}
|
||||
os_memcpy(magic_voice_s->buf,magic_voice_s->buf+nsamples,recv_frame_buf->len);
|
||||
}
|
||||
else {
|
||||
os_memcpy(send_frame_buf->data, recv_frame_buf->data, recv_frame_buf->len);
|
||||
}
|
||||
magic_voice_output:
|
||||
send_frame_buf->mtype = recv_frame_buf->mtype;
|
||||
send_frame_buf->stype = recv_frame_buf->stype;
|
||||
send_frame_buf->time = recv_frame_buf->time;
|
||||
send_frame_buf->len = recv_frame_buf->len;
|
||||
msi_output_fb(magic_voice_s->msi, send_frame_buf);
|
||||
}
|
||||
ret = RET_OK+1;
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_FREE_FB:
|
||||
{
|
||||
if(magic_voice_s) {
|
||||
struct framebuff *frame_buf = (struct framebuff *)param1;
|
||||
if(frame_buf->data) {
|
||||
MAGIC_VOICE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
fbpool_put(&magic_voice_s->tx_pool, frame_buf);
|
||||
}
|
||||
ret = RET_OK+1;
|
||||
break;
|
||||
}
|
||||
case MSI_CMD_POST_DESTROY:
|
||||
{
|
||||
if(magic_voice_s) {
|
||||
for(uint32_t i=0; i<MAX_MAGIC_VOICE_TXBUF; i++) {
|
||||
struct framebuff *frame_buf = (magic_voice_s->tx_pool.pool)+i;
|
||||
if(frame_buf->data) {
|
||||
MAGIC_VOICE_FREE(frame_buf->data);
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
}
|
||||
fbpool_destroy(&magic_voice_s->tx_pool);
|
||||
if(magic_voice_s->autpc_msi) {
|
||||
autpc_msi_deinit(magic_voice_s->autpc_msi);
|
||||
magic_voice_s->autpc_msi = NULL;
|
||||
}
|
||||
if(magic_voice_s->buf) {
|
||||
MAGIC_VOICE_FREE(magic_voice_s->buf);
|
||||
}
|
||||
MAGIC_VOICE_FREE(magic_voice_s);
|
||||
}
|
||||
ret = RET_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t magic_voice_set_type(uint8_t type)
|
||||
{
|
||||
int ret = RET_ERR;
|
||||
struct msi *msi = msi_find("SR_MAGIC_VOICE", 1);
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
magic_voice_struct *magic_voice_s = (magic_voice_struct*)msi->priv;
|
||||
magic_voice_s->new_type = type;
|
||||
ret = RET_OK;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t magic_voice_msi_add_output(const char *msi_name)
|
||||
{
|
||||
int ret = RET_ERR;
|
||||
struct msi *msi = msi_find("SR_MAGIC_VOICE", 1);
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
magic_voice_struct *magic_voice_s = (magic_voice_struct*)msi->priv;
|
||||
if(magic_voice_s->autpc_msi) {
|
||||
ret = autpc_msi_add_output(magic_voice_s->autpc_msi, msi_name);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t magic_voice_msi_del_output(const char *msi_name)
|
||||
{
|
||||
int ret = RET_ERR;
|
||||
struct msi *msi = msi_find("SR_MAGIC_VOICE", 1);
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
magic_voice_struct *magic_voice_s = (magic_voice_struct*)msi->priv;
|
||||
if(magic_voice_s->autpc_msi) {
|
||||
ret = autpc_msi_add_output(magic_voice_s->autpc_msi, msi_name);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t magic_voice_deinit(void)
|
||||
{
|
||||
int ret = RET_ERR;
|
||||
struct msi *msi = msi_find("SR_MAGIC_VOICE", 1);
|
||||
if(msi) {
|
||||
msi_put(msi);
|
||||
msi_destroy(msi);
|
||||
ret = RET_OK;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct msi *magic_voice_init(uint32_t samplerate, uint32_t size)
|
||||
{
|
||||
uint8_t msi_isnew = 0;
|
||||
struct framebuff *frame_buf = NULL;
|
||||
struct msi *msi = NULL;
|
||||
|
||||
if((samplerate != 8000) || (size != 160)) {
|
||||
os_printf("magic voice param abormal\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msi = msi_new("SR_MAGIC_VOICE", MAX_MAGIC_VOICE_RXBUF, &msi_isnew);
|
||||
if(msi == NULL) {
|
||||
os_printf("create magic voice msi fail\n");
|
||||
return NULL;
|
||||
}
|
||||
if(msi_isnew == 0) {
|
||||
return NULL;
|
||||
}
|
||||
magic_voice_struct *magic_voice_s = (magic_voice_struct*)MAGIC_VOICE_ZALLOC(sizeof(magic_voice_struct));
|
||||
if(magic_voice_s == NULL) {
|
||||
msi_destroy(msi);
|
||||
os_printf("alloc magic voice struct fail\n");
|
||||
return NULL;
|
||||
}
|
||||
fbpool_init(&magic_voice_s->tx_pool, MAX_MAGIC_VOICE_TXBUF);
|
||||
for(uint32_t i=0; i<MAX_MAGIC_VOICE_TXBUF; i++) {
|
||||
frame_buf = (magic_voice_s->tx_pool.pool)+i;
|
||||
frame_buf->data = NULL;
|
||||
}
|
||||
msi->priv = magic_voice_s;
|
||||
magic_voice_s->msi = msi;
|
||||
magic_voice_s->msi->enable = 1;
|
||||
magic_voice_s->msi->action = magic_voice_msi_action;
|
||||
magic_voice_s->autpc_msi = autpc_msi_init(samplerate, 100, 100, size, NULL);
|
||||
if(magic_voice_s->autpc_msi == NULL) {
|
||||
msi_destroy(msi);
|
||||
os_printf("magic voice create autpc msi fail\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
magic_voice_s->buf = (int16_t*)MAGIC_VOICE_MALLOC(size*2+320);
|
||||
if(magic_voice_s->buf == NULL) {
|
||||
msi_destroy(msi);
|
||||
os_printf("magic voice alloc buf fail\n");
|
||||
return NULL;
|
||||
}
|
||||
msi_add_output(msi, NULL, magic_voice_s->autpc_msi->name);
|
||||
magic_voice_s->new_type = original_voice;
|
||||
magic_voice_s->current_type = original_voice;
|
||||
return msi;
|
||||
}
|
||||
44
sdk/app/magic_voice/magic_voice.h
Normal file
44
sdk/app/magic_voice/magic_voice.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef _MAGIC_VOICE_H_
|
||||
#define _MAGIC_VOICE_H_
|
||||
|
||||
#include "lib/multimedia/msi.h"
|
||||
#include "lib/multimedia/framebuff.h"
|
||||
#include "lib/heap/av_heap.h"
|
||||
#include "lib/heap/av_psram_heap.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define MAGIC_VOICE_MALLOC av_psram_malloc
|
||||
#define MAGIC_VOICE_ZALLOC av_psram_zalloc
|
||||
#define MAGIC_VOICE_FREE av_psram_free
|
||||
#else
|
||||
#define MAGIC_VOICE_MALLOC av_malloc
|
||||
#define MAGIC_VOICE_ZALLOC av_zalloc
|
||||
#define MAGIC_VOICE_FREE av_free
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
original_voice,
|
||||
alien_voice,
|
||||
robot_voice,
|
||||
hight_voice,
|
||||
deep_voice,
|
||||
etourdi_voice
|
||||
}magic_voice_type;
|
||||
|
||||
typedef struct {
|
||||
struct msi *msi;
|
||||
struct msi *autpc_msi;
|
||||
struct fbpool tx_pool;
|
||||
int16_t *buf;
|
||||
uint8_t new_type;
|
||||
uint8_t current_type;
|
||||
uint32_t table_index;
|
||||
}magic_voice_struct;
|
||||
|
||||
int32_t magic_voice_set_type(uint8_t type);
|
||||
int32_t magic_voice_msi_add_output(const char *msi_name);
|
||||
int32_t magic_voice_msi_del_output(const char *msi_name);
|
||||
struct msi *magic_voice_init(uint32_t samplerate, uint32_t size);
|
||||
int32_t magic_voice_deinit(void);
|
||||
|
||||
#endif
|
||||
256
sdk/app/media/media.c
Normal file
256
sdk/app/media/media.c
Normal file
@@ -0,0 +1,256 @@
|
||||
#include <stdio.h>
|
||||
#include "diskio.h"
|
||||
#include "integer.h"
|
||||
#include "ff.h"
|
||||
#include "osal_file.h"
|
||||
#include "osal/string.h"
|
||||
|
||||
#define MIN(a,b) ( (a)>(b)?b:a )
|
||||
#define MAX(a,b) ( (a)>(b)?a:b )
|
||||
#define JPG_FILE_NAME "JPG"
|
||||
#define JPG_DIR "0:/DCIM"
|
||||
#define VIDEO_DIR "0:/VIDEO"
|
||||
#define VIDEO_FILE_NAME "AVI"
|
||||
|
||||
|
||||
|
||||
uint32_t file_mode (const char *mode);
|
||||
/************************************************************
|
||||
由于用的是全局变量,所以尽量单线程调用,否则可能有异常
|
||||
*************************************************************/
|
||||
FIL fp_jpg;
|
||||
char jpg_name[50];
|
||||
char jpg_indx[20];
|
||||
FIL fp_jpg;
|
||||
//视频录像文件名
|
||||
char video_name[50];
|
||||
|
||||
|
||||
static void create_avi_dir(char *dir)
|
||||
{
|
||||
//_os_printf("make avi dir\n");
|
||||
f_mkdir(dir);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t a2i(char *str)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
uint32_t indx =0;
|
||||
while(str[indx] != '\0'){
|
||||
if(str[indx] >= '0' && str[indx] <='9'){
|
||||
ret = ret*10+str[indx]-'0';
|
||||
}
|
||||
indx ++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void i2a(char *str,uint32_t data)
|
||||
{
|
||||
uint32_t temp = data;
|
||||
uint32_t tempa[64] ;
|
||||
uint32_t i = 0;
|
||||
tempa[i++] = '\0';
|
||||
tempa[i++] = data%10 + '0';
|
||||
while(temp /= 10)
|
||||
{
|
||||
tempa[i++] = temp%10 +'0';
|
||||
}
|
||||
while(*str++ = tempa[--i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void create_jpg_dir(char *dir)
|
||||
{
|
||||
// _os_printf("make jpg dir\n");
|
||||
f_mkdir(dir);
|
||||
}
|
||||
|
||||
//设置拍照文件的名字
|
||||
static void make_jpg_name(char *dest,char* indx,char *dir_name)
|
||||
{
|
||||
char *avi_dir = dir_name;
|
||||
char *publicname = JPG_FILE_NAME;
|
||||
char *end = ".jpg";
|
||||
#if 0
|
||||
uint32_t ofs = 0;
|
||||
ofs += str_cpy_noend(dest+ofs,avi_dir);
|
||||
ofs += str_cpy_noend(dest+ofs,publicname);
|
||||
ofs += str_cpy_noend(dest+ofs,indx);
|
||||
str_cpy(dest+ofs,end);
|
||||
#endif
|
||||
sprintf(dest,"%s%s%s%s",avi_dir,publicname,indx,end);
|
||||
}
|
||||
|
||||
int osal_fopen_no_malloc(F_FILE *fp,const char *filename,const char *mode){
|
||||
FRESULT res;
|
||||
uint32_t mod = file_mode (mode);
|
||||
|
||||
//fp = osal_malloc (sizeof (FIL));
|
||||
// if (fp == NULL) {
|
||||
// todo errno
|
||||
// _os_printf("osal_fopen malloc fail!\r\n");
|
||||
// return fp;
|
||||
// }
|
||||
// _os_printf("fp:%x\r\n",fp);
|
||||
res = f_open (fp, filename, mod);
|
||||
// _os_printf("res:%x\r\n",res);
|
||||
if (FR_OK != res) {
|
||||
// todo errno
|
||||
_os_printf("osal_fopen fail:%d\r\n",res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//创建拍照的文件夹并且创建jpg文件
|
||||
bool create_jpg_file(char *dir_name)
|
||||
{
|
||||
DIR avi_dir;
|
||||
FRESULT ret;
|
||||
FILINFO finfo;
|
||||
uint32_t indx= 0;
|
||||
int fp;
|
||||
|
||||
ret = f_opendir(&avi_dir,dir_name);
|
||||
if(ret != FR_OK){
|
||||
create_avi_dir(dir_name);
|
||||
f_opendir(&avi_dir,dir_name);
|
||||
}
|
||||
while(1){
|
||||
ret = f_readdir(&avi_dir,&finfo);
|
||||
if(ret != FR_OK || finfo.fname[0] == 0) break;
|
||||
indx = MAX(indx,a2i(finfo.fname));
|
||||
}
|
||||
f_closedir(&avi_dir);
|
||||
indx++;
|
||||
|
||||
sprintf(jpg_name,"%s/jpeg%d.%s",dir_name,indx,JPG_FILE_NAME);
|
||||
|
||||
|
||||
_os_printf("create jpg file name %s \r\n",jpg_name);
|
||||
fp = osal_fopen_no_malloc(&fp_jpg,jpg_name,"wb+");
|
||||
if(fp)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//获取标号最小的文件
|
||||
char *get_min_video_file(char *dir_name)
|
||||
{
|
||||
FRESULT ret;
|
||||
FILINFO finfo;
|
||||
int flag = 0;
|
||||
uint32_t indx= 0;
|
||||
uint32_t min = ~0;
|
||||
DIR avi_dir;
|
||||
ret = f_opendir(&avi_dir,dir_name);
|
||||
if(ret != FR_OK)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
while(1){
|
||||
ret = f_readdir(&avi_dir,&finfo);
|
||||
if(ret != FR_OK || finfo.fname[0] == 0) break;
|
||||
indx = MIN(min,a2i(finfo.fname));
|
||||
if(indx < min)
|
||||
{
|
||||
min = indx;
|
||||
sprintf(video_name,"%s/%s",dir_name,finfo.fname);
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
if(flag)
|
||||
{
|
||||
_os_printf("%s:%d name:%s\n",__FUNCTION__,__LINE__,video_name);
|
||||
return video_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void *create_video_file(char *dir_name)
|
||||
{
|
||||
DIR avi_dir;
|
||||
FRESULT ret;
|
||||
FILINFO finfo;
|
||||
uint32_t indx= 0;
|
||||
void *fp;
|
||||
|
||||
ret = f_opendir(&avi_dir,dir_name);
|
||||
if(ret != FR_OK){
|
||||
ret = f_mkdir(dir_name);
|
||||
if(ret!=FR_OK)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
ret = f_opendir(&avi_dir,dir_name);
|
||||
}
|
||||
if(ret!=FR_OK)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(1){
|
||||
ret = f_readdir(&avi_dir,&finfo);
|
||||
if(ret != FR_OK || finfo.fname[0] == 0) break;
|
||||
indx = MAX(indx,a2i(finfo.fname));
|
||||
}
|
||||
f_closedir(&avi_dir);
|
||||
indx++;
|
||||
|
||||
|
||||
sprintf(video_name,"%s/avi%d.%s",dir_name,indx,VIDEO_FILE_NAME);
|
||||
_os_printf("create video file name %s \r\n",video_name);
|
||||
fp = (void*)osal_fopen(video_name,"wb+");
|
||||
return fp;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void fatfs_create_jpg(){
|
||||
create_jpg_file(JPG_DIR);
|
||||
}
|
||||
|
||||
void fatfs_write_data(uint8_t *buf,uint32_t len){
|
||||
unsigned int bw;
|
||||
int res;
|
||||
//_os_printf("fatfs_write data:%d\r\n",len);
|
||||
res = f_write(&fp_jpg,buf,len,&bw);
|
||||
if (FR_OK != res){
|
||||
_os_printf("f_write fail:%d\r\n",res);
|
||||
}
|
||||
}
|
||||
|
||||
void fatfs_close_jpg(){
|
||||
int res;
|
||||
res = f_close(&fp_jpg);
|
||||
if (FR_OK != res){
|
||||
_os_printf("f_close fail:%d\r\n",res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user