Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
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;
|
||||
}
|
||||
Reference in New Issue
Block a user