Files
TAIXIN/sdk/app/avi_encode/avi_encode_msi2.c

393 lines
12 KiB
C
Raw Permalink Normal View History

#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;
}