1270 lines
38 KiB
C
1270 lines
38 KiB
C
#include "generic/typedef.h"
|
||
#include "fs/fs.h"
|
||
#include "simple_avi_unpkg.h"
|
||
#include "os/os_api.h"
|
||
#include "app_config.h"
|
||
|
||
#ifdef CONFIG_UI_ENABLE
|
||
|
||
#define UNPKG_S_ERR() do {printf("err : %s %d\n",__func__,__LINE__);return -1;}while(0)
|
||
#define UNPKG_U_ERR() do {printf("err : %s %d\n",__func__,__LINE__);return 0;}while(0)
|
||
#define AVI_DBG() printf("--->%s %d \n",__func__,__LINE__);
|
||
|
||
#define UNPKG_AVI_ERR() do {\
|
||
printf("\n\nmake sure avi_net_playback_unpkg_init/avi_net_preview_unpkg_init func is used before use this function ,"\
|
||
"and use avi_net_unpkg_exit func int the end!!!!\n\n");}while(0);
|
||
|
||
#define FD_READ_CHECK(len,idx)\
|
||
if(len != sizeof(idx)){\
|
||
fseek(fd, 0, SEEK_SET);\
|
||
UNPKG_S_ERR();\
|
||
}
|
||
|
||
#define FD_LEN_CHECK(offset,flen)\
|
||
if(offset > flen){\
|
||
fseek(fd, 0, SEEK_SET);\
|
||
printf("offset = %d , flen = %d \n",offset,flen);\
|
||
UNPKG_S_ERR();\
|
||
}
|
||
|
||
#define IDX_00DC ntohl(0x30306463)
|
||
#define IDX_01WB ntohl(0x30317762)
|
||
#define IDX_00WB ntohl(0x30307762)
|
||
|
||
#define REC_CYC_FILE_TIME 10 //分钟
|
||
#define AVI_AUDIO_NUM_TABLE (REC_CYC_FILE_TIME * 60 * 2 + 128)
|
||
|
||
struct avi_head_str {
|
||
UNPKG_JL_AVI_HEAD file_head;
|
||
FILE *fd;
|
||
u8 flag;
|
||
u32 flen;
|
||
u32 vdframe_cnt;
|
||
u32 vdframe_offset_cnt;
|
||
u32 adframe_cnt;
|
||
u32 adframe_offset_cnt;
|
||
u32 movi_addr;
|
||
|
||
u32 audio_chunk_num;
|
||
u32 video_chunk_num;
|
||
|
||
u32 last_ad_num;
|
||
u32 last_ad_sum;
|
||
u32 last_vd_num;
|
||
u32 last_vd_sum;
|
||
|
||
u32 idx1_addr;
|
||
u32 per_adframe_time;//每帧音频时间
|
||
float video_num_coefficient;
|
||
float audio_num_coefficient;
|
||
u8 audio_num_buff[AVI_AUDIO_NUM_TABLE];//存储音频每帧偏移量,1s2帧,3分钟360帧
|
||
u8 *video_num_buff;
|
||
};
|
||
static u8 avi_open_file_num = 0;
|
||
static struct avi_head_str avi_head_s[2];//0 preview , 1 playback
|
||
|
||
static int avi_get_video_audio_chunk_num(FILE *fd, u8 state);
|
||
|
||
static struct avi_head_str *avi_get_head_handler(u8 state)
|
||
{
|
||
struct avi_head_str *avi_info = NULL;
|
||
|
||
if (!state) {
|
||
avi_info = &avi_head_s[0];
|
||
} else {
|
||
avi_info = &avi_head_s[1];
|
||
}
|
||
|
||
return avi_info;
|
||
}
|
||
|
||
static int avi_read_head(FILE *fd, u8 state)
|
||
{
|
||
int len;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
memset(avi_info, 0, sizeof(struct avi_head_str));
|
||
|
||
if (fd == NULL) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
if (avi_info->flag && avi_info->fd == fd) {
|
||
return 0;
|
||
}
|
||
if (fseek(fd, 0, SEEK_SET)) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
len = fread(&avi_info->file_head, sizeof(UNPKG_JL_AVI_HEAD), 1, fd);
|
||
if (len != sizeof(UNPKG_JL_AVI_HEAD)) {
|
||
fseek(fd, 0, SEEK_SET);
|
||
UNPKG_S_ERR();
|
||
}
|
||
avi_info->flen = flen(fd);
|
||
avi_info->fd = fd;
|
||
avi_info->flag = true;
|
||
avi_info->movi_addr = 512 - 4;
|
||
fseek(fd, 0, SEEK_SET);
|
||
return 0;
|
||
}
|
||
|
||
|
||
int avi_net_playback_unpkg_init(FILE *fd, u8 state)//state : 0 preview , 1 playback
|
||
{
|
||
if (fd) {
|
||
avi_read_head(fd, state);
|
||
avi_get_video_audio_chunk_num(fd, state);
|
||
avi_open_file_num++;
|
||
return 0;
|
||
}
|
||
return -1;
|
||
}
|
||
int avi_net_preview_unpkg_init(FILE *fd, u8 state)
|
||
{
|
||
if (fd) {
|
||
avi_read_head(fd, state);
|
||
avi_open_file_num++;
|
||
return 0;
|
||
}
|
||
return -1;
|
||
}
|
||
int avi_net_unpkg_exit(FILE *fd, u8 state)
|
||
{
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
if (fd) {
|
||
if (avi_open_file_num == 0) {
|
||
avi_open_file_num = 0;
|
||
} else {
|
||
avi_open_file_num--;
|
||
}
|
||
if (avi_info->video_num_buff) {
|
||
free(avi_info->video_num_buff);
|
||
avi_info->video_num_buff = NULL;
|
||
}
|
||
/*memset(avi_info,0,sizeof(struct avi_head_str));*/
|
||
return 0;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
int is_vaild_avi_file(FILE *fd, u8 state)
|
||
{
|
||
int riff = ntohl(0x52494646);//"riff"
|
||
int avi = ntohl(0x41564920);//"avi "
|
||
int err;
|
||
int fsize;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
|
||
if (!fd) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (avi_info->flag && avi_info->fd == fd) {
|
||
goto get_data;
|
||
} else {
|
||
UNPKG_AVI_ERR();
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
get_data:
|
||
if (avi_info->file_head.avih.dwTotalFrames == 0 || avi_info->file_head.file_size == 0) {
|
||
UNPKG_U_ERR();
|
||
}
|
||
fsize = flen(fd);
|
||
if (avi_info->file_head.file_size > fsize) {
|
||
printf("avi file is destroy !!!\n\n");
|
||
return 0;
|
||
}
|
||
if (avi_info->file_head.riff == riff || avi_info->file_head.file_type == avi) {
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int avi_is_has_audio(FILE *fd, u8 state)
|
||
{
|
||
int err;
|
||
int auds = ntohl(0x61756473);//"auds"
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
|
||
if (!fd) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (avi_info->flag && avi_info->fd == fd) {
|
||
goto get_data;
|
||
} else {
|
||
UNPKG_AVI_ERR();
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
get_data:
|
||
if (avi_info->file_head.aud_strh.fccType == auds && avi_info->file_head.aud_strh.dwLength > 0) {
|
||
return 0;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
int avi_get_fps(FILE *fd, u8 state)
|
||
{
|
||
int fps;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
if (!fd) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (avi_info->flag && avi_info->fd == fd) {
|
||
goto get_data;
|
||
} else {
|
||
UNPKG_AVI_ERR();
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
get_data:
|
||
fps = avi_info->file_head.vid_strh.dwRate;
|
||
// printf("file fps : %d \n",fps);
|
||
return fps;
|
||
}
|
||
|
||
int avi_get_file_time(FILE *fd, u8 state)
|
||
{
|
||
int time;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
if (!fd) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (avi_info->flag && avi_info->fd == fd) {
|
||
goto get_data;
|
||
} else {
|
||
UNPKG_AVI_ERR();
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
get_data:
|
||
time = 1000000 / avi_info->file_head.avih.dwMicroSecPerFrame;
|
||
time = avi_info->file_head.avih.dwTotalFrames / (time > 0 ? time : avi_info->file_head.avih.dwTotalFrames);
|
||
time = time > 0 ? time : 1;
|
||
/*printf("file time : %d \n", time);*/
|
||
return time;
|
||
}
|
||
|
||
int avi_get_width_height(FILE *fd, void *__info, u8 state)
|
||
{
|
||
AVI_UNPKG_INFO *info = (AVI_UNPKG_INFO *)__info;
|
||
int err;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
if (!fd) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (avi_info->flag && avi_info->fd == fd) {
|
||
goto get_data;
|
||
} else {
|
||
UNPKG_AVI_ERR();
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
get_data:
|
||
info->height = avi_info->file_head.avih.dwHeight;
|
||
info->length = avi_info->file_head.avih.dwWidth;
|
||
/*printf("height : %d , length : %d \n",info->height,info->length);*/
|
||
return 0;
|
||
}
|
||
|
||
int avi_get_audio_sample_rate(FILE *fd, u8 state)
|
||
{
|
||
int err;
|
||
int rate;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
if (!fd) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (avi_info->flag && avi_info->fd == fd) {
|
||
goto get_data;
|
||
} else {
|
||
UNPKG_AVI_ERR();
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
get_data:
|
||
rate = avi_info->file_head.aud_strh.dwRate;
|
||
/*if(!avi_info->audio_chunk_num)*/
|
||
/*return 0;*/
|
||
// printf("rate : %d \n",rate);
|
||
return rate;
|
||
|
||
}
|
||
|
||
int avi_audio_base_to_get_video_frame(u32 audio_num, u8 state) //线性补偿,audio_num:0,1....n
|
||
{
|
||
double vd_num;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
if (avi_info->video_num_coefficient < 0.000001) {
|
||
return 0;
|
||
}
|
||
audio_num += 1;
|
||
vd_num = (double)(avi_info->video_num_coefficient * audio_num);
|
||
return (int)vd_num;
|
||
}
|
||
int avi_video_base_to_get_audio_frame(int vd_num, u8 state) //线性补偿,vd_num:0,1.....n
|
||
{
|
||
double ad_num;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
if (avi_info->audio_num_coefficient < 0.000001) {
|
||
return 0;
|
||
}
|
||
vd_num += 1;
|
||
ad_num = (double)(avi_info->audio_num_coefficient * vd_num);
|
||
return (int)ad_num;
|
||
}
|
||
|
||
static int avi_get_audio_perfram_size(FILE *fd, int addr, u8 state)
|
||
{
|
||
AVI_INDEX_INFO index_info = {0};
|
||
int index_info_len = sizeof(AVI_INDEX_INFO);
|
||
int i;
|
||
int cnt = 0;
|
||
int len;
|
||
|
||
if (fd == NULL) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
read_vd:
|
||
if (ftell(fd) > (flen(fd) - sizeof(AVI_INDEX_INFO))) {
|
||
return -1;
|
||
}
|
||
if (fseek(fd, addr + cnt * index_info_len, SEEK_SET)) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
len = fread(&index_info, index_info_len, 1, fd);
|
||
if (len != index_info_len) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if ((index_info.dwChunkId == 0 && index_info.dwOffset == 0 && index_info.dwSize == 0)
|
||
|| (index_info.dwChunkId != IDX_00DC && index_info.dwChunkId != IDX_01WB && index_info.dwChunkId != IDX_00WB)) {
|
||
return 0;
|
||
}
|
||
if (index_info.dwSize == 0) {
|
||
cnt++;
|
||
goto read_vd;
|
||
}
|
||
if (index_info.dwChunkId == IDX_01WB || index_info.dwChunkId == IDX_00WB) {
|
||
return index_info.dwSize;
|
||
}
|
||
cnt++;
|
||
goto read_vd;
|
||
return -1;
|
||
}
|
||
|
||
static int avi_other_find_index(FILE *fd, u8 state)
|
||
{
|
||
int offset;
|
||
int index_addr;
|
||
int idx1 = ntohl(0x69647831);//"index1"
|
||
int hdrl = ntohl(0x6864726c);//"hdrl"
|
||
int avih = ntohl(0x61766968);//"avih"
|
||
int list = ntohl(0x4c495354);//"list"
|
||
int strl = ntohl(0x7374726c);//"strl"
|
||
int strh = ntohl(0x73747268);//"strh"
|
||
int strf = ntohl(0x73747266);//"strf"
|
||
int junk = ntohl(0x4a554e4b);//"junk"
|
||
int movi = ntohl(0x6d6f7669);//"movi"
|
||
int len;
|
||
int nidx_len;
|
||
int nidx_idx;
|
||
int err;
|
||
int addr;
|
||
float vd_presec_ms;
|
||
float ad_presec_ms;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
u32 offset_addr;
|
||
u32 fd_len;
|
||
|
||
offset_addr = 16;
|
||
fseek(fd, 0, SEEK_END);
|
||
|
||
avi_info->flen = flen(fd);
|
||
if (avi_info->flen <= 0 /* || avi_info->flen == 32768*/) { //文件系统BUG,读取方式是"rb"时候flen = 32768
|
||
return -1;
|
||
}
|
||
fd_len = avi_info->flen;
|
||
fseek(fd, offset_addr, SEEK_SET);
|
||
len = fread(&nidx_len, sizeof(nidx_len), 1, fd);
|
||
FD_READ_CHECK(len, nidx_len);
|
||
avi_info->file_head.hdrl_size = nidx_len;
|
||
|
||
offset_addr += sizeof(nidx_len);
|
||
fseek(fd, offset_addr, SEEK_SET);
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
if (nidx_idx != hdrl) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
/*printf("--->hdrl \n");*/
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
if (avih != nidx_idx) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
len = fread(&nidx_len, sizeof(nidx_len), 1, fd);
|
||
FD_READ_CHECK(len, nidx_len);
|
||
/*printf("--->avih , nidx_len = %d\n",nidx_len);*/
|
||
fread(&avi_info->file_head.avih.dwMicroSecPerFrame, nidx_len, 1, fd);
|
||
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
if (list != nidx_idx) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
/*printf("--->list video\n");*/
|
||
fread(&avi_info->file_head.strl_vidsize, sizeof(int), 1, fd);
|
||
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
if (strl != nidx_idx) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
/*printf("--->strl\n");*/
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
if (strh != nidx_idx) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
len = fread(&nidx_len, sizeof(nidx_len), 1, fd);
|
||
FD_READ_CHECK(len, nidx_len);
|
||
fread(&avi_info->file_head.vid_strh.fccType, nidx_len, 1, fd);
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
|
||
/*printf("--->strf\n");*/
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
if (strf != nidx_idx) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
len = fread(&nidx_len, sizeof(nidx_len), 1, fd);
|
||
FD_READ_CHECK(len, nidx_len);
|
||
fread(&avi_info->file_head.vid_strf.biSize, nidx_len, 1, fd);
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
|
||
offset_addr = ftell(fd);
|
||
while (1) {
|
||
FD_LEN_CHECK(offset_addr, fd_len);
|
||
fseek(fd, offset_addr, SEEK_SET);
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
if (list == nidx_idx) {
|
||
break;
|
||
}
|
||
offset_addr += sizeof(nidx_idx);
|
||
fseek(fd, offset_addr, SEEK_SET);
|
||
FD_LEN_CHECK(offset_addr, fd_len);
|
||
len = fread(&nidx_len, sizeof(nidx_len), 1, fd);
|
||
FD_READ_CHECK(len, nidx_len);
|
||
offset_addr += sizeof(nidx_idx);
|
||
offset_addr += nidx_len;
|
||
}
|
||
/*printf("--->list audio\n");*/
|
||
fread(&avi_info->file_head.strl_audsize, sizeof(int), 1, fd);
|
||
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
if (strl != nidx_idx) {
|
||
fseek(fd, offset_addr, SEEK_SET);
|
||
goto mov_find;
|
||
}
|
||
/*printf("--->strl audio\n");*/
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
if (strh != nidx_idx) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
len = fread(&nidx_len, sizeof(nidx_len), 1, fd);
|
||
FD_READ_CHECK(len, nidx_len);
|
||
fread(&avi_info->file_head.aud_strh.fccType, nidx_len, 1, fd);
|
||
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
/*printf("--->strf audio\n");*/
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
if (strf != nidx_idx) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
len = fread(&nidx_len, sizeof(nidx_len), 1, fd);
|
||
FD_READ_CHECK(len, nidx_len);
|
||
fread(&avi_info->file_head.aud_strf.wFormatTag, nidx_len, 1, fd);
|
||
/*printf("---> next index = 0x%x , offset = 0x%x, line = %d\n",nidx_idx, ftell(fd),__LINE__);*/
|
||
mov_find:
|
||
offset_addr = ftell(fd);
|
||
while (1) {
|
||
FD_LEN_CHECK(offset_addr, fd_len);
|
||
fseek(fd, offset_addr, SEEK_SET);
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
offset_addr += sizeof(nidx_idx);
|
||
if (idx1 == nidx_idx) {
|
||
offset_addr -= sizeof(nidx_len);
|
||
fseek(fd, offset_addr, SEEK_SET);
|
||
break;
|
||
}
|
||
FD_LEN_CHECK(offset_addr, fd_len);
|
||
fseek(fd, offset_addr, SEEK_SET);
|
||
len = fread(&nidx_len, sizeof(nidx_len), 1, fd);
|
||
FD_READ_CHECK(len, nidx_len);
|
||
offset_addr += sizeof(nidx_len);
|
||
if (list == nidx_idx) {
|
||
FD_LEN_CHECK(offset_addr, fd_len);
|
||
fseek(fd, offset_addr, SEEK_SET);
|
||
len = fread(&nidx_idx, sizeof(nidx_idx), 1, fd);
|
||
FD_READ_CHECK(len, nidx_idx);
|
||
if (movi == nidx_idx) {
|
||
avi_info->movi_addr = ftell(fd) - 4;
|
||
}
|
||
}
|
||
offset_addr += nidx_len;
|
||
}
|
||
printf("get index ok ,avi_info->movi_addr = 0x%x\n", avi_info->movi_addr);
|
||
return 0;
|
||
}
|
||
|
||
|
||
static u32 avi_find_index_addr(FILE *fd, u8 state)
|
||
{
|
||
int offset;
|
||
int index_addr;
|
||
int idx1 = ntohl(0x69647831);//"index1"
|
||
int len;
|
||
int err;
|
||
int addr;
|
||
float vd_presec_ms;
|
||
float ad_presec_ms;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
|
||
struct idex1_str {
|
||
int str;
|
||
int len;
|
||
} idex1_head = {0};
|
||
|
||
if (fd == NULL) {
|
||
UNPKG_U_ERR();
|
||
}
|
||
|
||
if (avi_info->flag && avi_info->fd == fd) {
|
||
goto get_data;
|
||
} else {
|
||
UNPKG_AVI_ERR();
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
get_data:
|
||
if (avi_info->idx1_addr) {
|
||
return avi_info->idx1_addr;
|
||
}
|
||
|
||
// 2 . 读取AVI文件头
|
||
if (!avi_info->flag || avi_info->fd != fd) {
|
||
UNPKG_U_ERR();
|
||
}
|
||
|
||
index_addr = avi_info->file_head.len - 4;//音视频数据内容大小
|
||
addr = sizeof(UNPKG_JL_AVI_HEAD) + index_addr;
|
||
|
||
//3 . 跳转到索引表处
|
||
if (fseek(fd, addr, SEEK_SET)) {
|
||
fseek(fd, 0, SEEK_SET);
|
||
UNPKG_U_ERR();
|
||
}
|
||
|
||
read_index:
|
||
//4 . 读取"inde1"块的头和整个索引表的长度
|
||
len = fread(&idex1_head, sizeof(struct idex1_str), 1, fd);
|
||
addr += sizeof(struct idex1_str);
|
||
if (len != sizeof(struct idex1_str)) {
|
||
fseek(fd, 0, SEEK_SET);
|
||
UNPKG_U_ERR();
|
||
}
|
||
|
||
if (idex1_head.str != idx1) {
|
||
fseek(fd, 0, SEEK_SET);
|
||
if (!avi_other_find_index(fd, state)) {
|
||
addr = ftell(fd);
|
||
/*printf("--->get addr = 0x%x\n",addr);*/
|
||
goto read_index;
|
||
}
|
||
UNPKG_U_ERR();
|
||
}
|
||
|
||
if (!avi_info->per_adframe_time) {
|
||
len = avi_get_audio_perfram_size(fd, addr, state);
|
||
if (len > 0) {
|
||
avi_info->per_adframe_time = ((float)len / (avi_info->file_head.aud_strh.dwRate * avi_info->file_head.aud_strf.nBlockAlign)) * 1000;
|
||
ad_presec_ms = (float)((float)len / (avi_info->file_head.aud_strh.dwRate * avi_info->file_head.aud_strf.nBlockAlign)) * 1000;
|
||
vd_presec_ms = (float)avi_info->file_head.avih.dwMicroSecPerFrame / 1000;
|
||
avi_info->video_num_coefficient = (float)ad_presec_ms / vd_presec_ms;
|
||
avi_info->audio_num_coefficient = (float)vd_presec_ms / ad_presec_ms;
|
||
/*printf("ad_presec_ms : %f , %f , %f \n",ad_presec_ms,vd_presec_ms,avi_info->video_num_coefficient);*/
|
||
} else {
|
||
printf("get AVI audio frame err!!!!! \n");
|
||
avi_info->per_adframe_time = ((float)8184 / (8000 * 2)) * 1000; //ms
|
||
}
|
||
}
|
||
//5 . 返回第一个索引表地址
|
||
avi_info->idx1_addr = addr;
|
||
|
||
//6 . 恢复文件指针
|
||
fseek(fd, 0, SEEK_SET);
|
||
return avi_info->idx1_addr;
|
||
}
|
||
|
||
static int avi_audio_get_offset_cnt(FILE *fd, int num, u8 state) //第一帧从1开始,...
|
||
{
|
||
int i;
|
||
int addr = 0;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
|
||
if (!avi_info->flag || avi_info->fd != fd) {
|
||
UNPKG_AVI_ERR();
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (num > avi_info->audio_chunk_num) {
|
||
return -1;
|
||
}
|
||
if (num <= 1) {
|
||
avi_info->last_ad_num = 0;
|
||
avi_info->last_ad_sum = 0;
|
||
num = 1;
|
||
}
|
||
if (num < avi_info->last_ad_num) {
|
||
for (i = 0; i < num; i++) { //任意帧
|
||
addr += avi_info->audio_num_buff[i];
|
||
}
|
||
} else {
|
||
addr += avi_info->last_ad_sum;
|
||
for (i = avi_info->last_ad_num; i < num; i++) { //升序帧,第一帧从1开始,...
|
||
addr += avi_info->audio_num_buff[i];
|
||
}
|
||
}
|
||
avi_info->last_ad_num = num;
|
||
avi_info->last_ad_sum = addr;
|
||
return addr;
|
||
}
|
||
static int avi_video_get_offset_cnt(FILE *fd, int num, u8 state) //第一帧从1开始,...
|
||
{
|
||
int i;
|
||
int addr = 0;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
|
||
if (!avi_info->flag || avi_info->fd != fd) {
|
||
UNPKG_AVI_ERR();
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
if (num <= 1) {
|
||
avi_info->last_vd_num = 0;
|
||
avi_info->last_vd_sum = 0;
|
||
num = 1;
|
||
return 0;
|
||
}
|
||
|
||
if (num > avi_info->video_chunk_num && !state) { //回放模式
|
||
return -1;
|
||
}
|
||
|
||
if (num < avi_info->last_vd_num) {
|
||
for (i = 0; i < num; i++) { //任意帧
|
||
addr += avi_info->video_num_buff[i];
|
||
}
|
||
} else {
|
||
addr += avi_info->last_vd_sum;
|
||
for (i = avi_info->last_vd_num; i < num; i++) { //升序帧,第一帧从1开始,...
|
||
addr += avi_info->video_num_buff[i];
|
||
}
|
||
}
|
||
avi_info->last_vd_num = num;
|
||
avi_info->last_vd_sum = addr;
|
||
return addr;
|
||
}
|
||
|
||
static int avi_get_video_audio_chunk_num(FILE *fd, u8 state) //获取整个视频的音视频帧数
|
||
{
|
||
int num = 0;
|
||
int cnt = 0;
|
||
AVI_INDEX_INFO index_info = {0};
|
||
int index_info_len = sizeof(AVI_INDEX_INFO);
|
||
int addr;
|
||
int len;
|
||
int start = 0, end = 0;
|
||
int vdstart = 0, vdend = 0;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
|
||
if (avi_info->audio_chunk_num) {
|
||
return avi_info->audio_chunk_num;
|
||
}
|
||
|
||
addr = (int)avi_find_index_addr(fd, state);
|
||
if (addr <= 0) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (fseek(fd, addr + cnt * index_info_len, SEEK_SET)) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
if (!avi_info->video_num_buff) {
|
||
avi_info->video_num_buff = zalloc(avi_info->file_head.avih.dwTotalFrames);//回放模式
|
||
}
|
||
if (!avi_info->video_num_buff) {
|
||
printf("%s no mem err !!!!!\n", __func__);
|
||
UNPKG_S_ERR();
|
||
}
|
||
|
||
for (;;) {
|
||
if (ftell(fd) >= avi_info->flen) {
|
||
break;
|
||
}
|
||
len = fread(&index_info, index_info_len, 1, fd);
|
||
if (len != index_info_len) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if ((index_info.dwChunkId == 0 && index_info.dwOffset == 0 && index_info.dwSize == 0)
|
||
|| (index_info.dwChunkId != IDX_00DC && index_info.dwChunkId != IDX_01WB && index_info.dwChunkId != IDX_00WB)) {
|
||
break;
|
||
}
|
||
|
||
if (index_info.dwChunkId == IDX_01WB || index_info.dwChunkId == IDX_00WB) {
|
||
start = cnt + num;
|
||
if (num < sizeof(avi_info->audio_num_buff)) {
|
||
avi_info->audio_num_buff[num] = start - end;
|
||
}
|
||
end = start;
|
||
num++;
|
||
avi_info->audio_chunk_num = num;
|
||
} else {
|
||
vdstart = cnt + num;
|
||
if (cnt < avi_info->file_head.avih.dwTotalFrames) {
|
||
avi_info->video_num_buff[cnt] = vdstart - vdend;
|
||
}
|
||
vdend = vdstart;
|
||
cnt++;
|
||
}
|
||
}
|
||
avi_info->video_chunk_num = cnt;
|
||
printf("audio_chunk_num num : %d \n", num);
|
||
printf("video_chunk_num num : %d \n", cnt);
|
||
return num;
|
||
}
|
||
int avi_get_video_num(FILE *fd, int offset_ms, u8 state)
|
||
{
|
||
int cnt;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
if (!avi_info->flag || avi_info->fd != fd) {
|
||
UNPKG_AVI_ERR();
|
||
UNPKG_S_ERR();
|
||
}
|
||
cnt = offset_ms / (avi_info->file_head.avih.dwMicroSecPerFrame / 1000); //计算对应帧数
|
||
return cnt;
|
||
}
|
||
int avi_get_audio_chunk_num(FILE *fd, u8 state) //获取整个视频的音频帧数
|
||
{
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
return avi_info->audio_chunk_num;
|
||
}
|
||
int avi_get_video_chunk_num(FILE *fd, u8 state) //获取整个视频的音频帧数
|
||
{
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
return avi_info->video_chunk_num;
|
||
}
|
||
//读对应视频帧数
|
||
int avi_video_get_frame(FILE *fd, int offset_num, u8 *buf, u32 buf_len, u8 state)
|
||
{
|
||
int movi = ntohl(0x6d6f7669);//"movi"
|
||
u32 addr;
|
||
int len;
|
||
int all_len;
|
||
int idx_send_cnt;
|
||
int idx_offset;
|
||
AVI_INDEX_INFO index_info = {0};
|
||
int index_info_len = sizeof(AVI_INDEX_INFO);
|
||
int i;
|
||
int cnt = 0;
|
||
int offset_addr;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
struct idex1_str {
|
||
int str;
|
||
int len;
|
||
} idex1_head = {0};
|
||
|
||
if (fd == NULL) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
addr = avi_find_index_addr(fd, state);
|
||
if (!addr) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
avi_info->vdframe_offset_cnt = offset_num;//计算对应帧数
|
||
if (avi_info->vdframe_offset_cnt > avi_info->file_head.avih.dwTotalFrames) {
|
||
/*avi_info->vdframe_offset_cnt = avi_info->file_head.avih.dwTotalFrames;*/
|
||
return -1;
|
||
}
|
||
cnt = avi_video_get_offset_cnt(avi_info->fd, avi_info->vdframe_offset_cnt, state);
|
||
/*printf("video cnt : %d , offset_num : %d \n",cnt,offset_num);*/
|
||
if (cnt < 0) {
|
||
return -1;
|
||
}
|
||
read_vd:
|
||
offset_addr = addr + cnt * index_info_len;
|
||
if (offset_addr > avi_info->flen) {
|
||
return 0;
|
||
}
|
||
if (fseek(fd, offset_addr, SEEK_SET)) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
len = fread(&index_info, index_info_len, 1, fd);
|
||
if (len != index_info_len) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if ((index_info.dwChunkId == 0 && index_info.dwOffset == 0 && index_info.dwSize == 0)
|
||
|| (index_info.dwChunkId != IDX_00DC && index_info.dwChunkId != IDX_01WB && index_info.dwChunkId != IDX_00WB)) {
|
||
printf("end of video AVI file ... \n");
|
||
return 0;
|
||
}
|
||
if (index_info.dwSize == 0) {
|
||
cnt++;
|
||
goto read_vd;
|
||
}
|
||
if (index_info.dwChunkId == IDX_00DC) {
|
||
idx_offset = index_info.dwOffset + avi_info->movi_addr + sizeof(struct idex1_str);
|
||
if (offset_addr > avi_info->flen || offset_addr < 0) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (fseek(fd, idx_offset, SEEK_SET)) {
|
||
printf("idx_offset : %d , index_info.dwOffset : %d \n", idx_offset, index_info.dwOffset);
|
||
UNPKG_S_ERR();
|
||
}
|
||
all_len = 0;
|
||
} else {
|
||
cnt++;
|
||
goto read_vd;
|
||
}
|
||
/*printf("video frame len : %d \n", index_info.dwSize);*/
|
||
if (index_info.dwSize > buf_len) {
|
||
printf("\n\n\n!!!!!err video data buff len not enough , need : %d ,but buflen is %d !!!!!!!!!!!\n\n", index_info.dwSize, buf_len);
|
||
/*ASSERT(0, "!err video data buff len not enough");*/
|
||
return 0;
|
||
}
|
||
/*printf("--->idx_offset = 0x%x ,index_info.dwOffset = 0x%x, index_info.dwSize = %d\n",idx_offset,index_info.dwOffset,index_info.dwSize);*/
|
||
|
||
all_len = fread(buf, index_info.dwSize, 1, fd);
|
||
|
||
/*printf("video frame all_len : %d \n", all_len);*/
|
||
if (all_len != index_info.dwSize) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
avi_info->vdframe_cnt = offset_num;
|
||
return all_len;
|
||
}
|
||
int avi_video_set_frame_addr(FILE *fd, int offset_num, u8 state)
|
||
{
|
||
int movi = ntohl(0x6d6f7669);//"movi"
|
||
u32 addr;
|
||
int len;
|
||
int all_len;
|
||
int idx_send_cnt;
|
||
int idx_offset;
|
||
AVI_INDEX_INFO index_info = {0};
|
||
int index_info_len = sizeof(AVI_INDEX_INFO);
|
||
int i;
|
||
int cnt = 0;
|
||
int offset_addr;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
struct idex1_str {
|
||
int str;
|
||
int len;
|
||
} idex1_head = {0};
|
||
|
||
if (fd == NULL) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
addr = avi_find_index_addr(fd, state);
|
||
if (!addr) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
avi_info->vdframe_offset_cnt = offset_num;//计算对应帧数
|
||
if (avi_info->vdframe_offset_cnt > avi_info->file_head.avih.dwTotalFrames) {
|
||
avi_info->vdframe_offset_cnt = avi_info->file_head.avih.dwTotalFrames;
|
||
/*UNPKG_S_ERR();*/
|
||
}
|
||
cnt = avi_video_get_offset_cnt(avi_info->fd, offset_num, state);
|
||
if (cnt < 0) {
|
||
return -1;
|
||
}
|
||
// printf("cnt : %d ,vdframe_offset_cnt : %d\n",cnt,avi_info->vdframe_offset_cnt);
|
||
read_vd:
|
||
offset_addr = addr + cnt * index_info_len;
|
||
if (offset_addr > avi_info->flen) {
|
||
return 0;
|
||
}
|
||
if (fseek(fd, offset_addr, SEEK_SET)) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
len = fread(&index_info, index_info_len, 1, fd);
|
||
if (len != index_info_len) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if ((index_info.dwChunkId == 0 && index_info.dwOffset == 0 && index_info.dwSize == 0)
|
||
|| (index_info.dwChunkId != IDX_00DC && index_info.dwChunkId != IDX_01WB && index_info.dwChunkId != IDX_00WB)) {
|
||
printf("end of video AVI file ... \n");
|
||
return 0;
|
||
}
|
||
if (index_info.dwSize == 0) {
|
||
cnt++;
|
||
goto read_vd;
|
||
}
|
||
if (index_info.dwChunkId == IDX_00DC) {
|
||
idx_offset = index_info.dwOffset + avi_info->movi_addr + sizeof(struct idex1_str);
|
||
if (offset_addr > avi_info->flen || offset_addr < 0) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (fseek(fd, idx_offset, SEEK_SET)) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
} else {
|
||
cnt++;
|
||
/*avi_info->adframe_cnt++;*/
|
||
goto read_vd;
|
||
}
|
||
return index_info.dwSize;
|
||
}
|
||
|
||
|
||
//读对应音频帧数
|
||
int avi_audio_get_frame(FILE *fd, int offset_num, u8 *buf, u32 buf_len, u8 state) //offset_num : 1....n
|
||
{
|
||
u32 addr;
|
||
int len;
|
||
int all_len;
|
||
int movi = ntohl(0x6d6f7669);//"movi"
|
||
int idx_send_cnt;
|
||
int idx_offset;
|
||
AVI_INDEX_INFO index_info = {0};
|
||
int index_info_len = sizeof(AVI_INDEX_INFO);
|
||
int i;
|
||
int cnt = 0;
|
||
int offset_addr;
|
||
int last_addr = 0;
|
||
struct avi_head_str *avi_info = avi_get_head_handler(state);
|
||
struct idex1_str {
|
||
int str;
|
||
int len;
|
||
} idex1_head = {0};
|
||
if (fd == NULL) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
addr = avi_find_index_addr(fd, state);
|
||
if (!addr) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (offset_num > avi_info->audio_chunk_num) {
|
||
/*printf("Warnning : offset_num > avi_info->audio_chunk_num \n");*/
|
||
return 0;
|
||
}
|
||
last_addr = ftell(fd);
|
||
avi_info->adframe_offset_cnt = 0;
|
||
cnt = avi_audio_get_offset_cnt(fd, offset_num, state);
|
||
if (cnt < 0) {
|
||
return -1;
|
||
}
|
||
/*printf("audio cnt : %d \n",cnt);*/
|
||
read_vd:
|
||
offset_addr = addr + cnt * index_info_len;
|
||
if (offset_addr > avi_info->flen) {
|
||
fseek(fd, last_addr, SEEK_SET);
|
||
return 0;
|
||
}
|
||
if (fseek(fd, offset_addr, SEEK_SET)) {
|
||
fseek(fd, last_addr, SEEK_SET);
|
||
UNPKG_S_ERR();
|
||
}
|
||
len = fread(&index_info, index_info_len, 1, fd);
|
||
if (len != index_info_len) {
|
||
fseek(fd, last_addr, SEEK_SET);
|
||
UNPKG_S_ERR();
|
||
}
|
||
if ((index_info.dwChunkId == 0 && index_info.dwOffset == 0 && index_info.dwSize == 0)
|
||
|| (index_info.dwChunkId != IDX_00DC && index_info.dwChunkId != IDX_01WB && index_info.dwChunkId != IDX_00WB)) {
|
||
fseek(fd, last_addr, SEEK_SET);
|
||
/*printf("end of audio AVI file ... \n");*/
|
||
return 0;
|
||
}
|
||
if (index_info.dwSize == 0) {
|
||
cnt++;
|
||
goto read_vd;
|
||
}
|
||
if (index_info.dwChunkId == IDX_01WB || index_info.dwChunkId == IDX_00WB) {
|
||
idx_offset = index_info.dwOffset + avi_info->movi_addr + sizeof(struct idex1_str);
|
||
if (offset_addr > avi_info->flen || offset_addr < 0) {
|
||
UNPKG_S_ERR();
|
||
}
|
||
if (fseek(fd, idx_offset, SEEK_SET)) {
|
||
fseek(fd, last_addr, SEEK_SET);
|
||
UNPKG_S_ERR();
|
||
}
|
||
all_len = 0;
|
||
} else {
|
||
cnt++;
|
||
goto read_vd;
|
||
}
|
||
if (index_info.dwSize > buf_len) {
|
||
printf("\n\n\n!!!!!err audio data buff len not enough , need : %d ,but buflen is %d !!!!!!!!!!!\n\n", index_info.dwSize, buf_len);
|
||
/*ASSERT(0, "!err audio data buff len not enough");*/
|
||
return 0;
|
||
}
|
||
all_len = fread(buf, index_info.dwSize, 1, fd);
|
||
if (all_len != index_info.dwSize) {
|
||
fseek(fd, last_addr, SEEK_SET);
|
||
UNPKG_S_ERR();
|
||
}
|
||
avi_info->adframe_cnt++;
|
||
fseek(fd, last_addr, SEEK_SET);
|
||
return all_len;
|
||
}
|
||
|
||
#if 1
|
||
#include "asm/jpeg_codec.h"
|
||
#include "system/includes.h"
|
||
#include "os/os_api.h"
|
||
#include "yuv_to_rgb.h"
|
||
#define AVI_UNPKG_DECODE_TEST 0
|
||
|
||
int storage_device_ready(void);
|
||
struct yuv_recv {
|
||
volatile unsigned char *y;
|
||
volatile unsigned char *u;
|
||
volatile unsigned char *v;
|
||
volatile int y_size;
|
||
volatile int u_size;
|
||
volatile int v_size;
|
||
volatile int recv_size;
|
||
volatile int size;
|
||
volatile char complit;
|
||
volatile int yuv_cb_cnt;
|
||
};
|
||
static int yuv_out_cb(void *priv, struct YUV_frame_data *p)
|
||
{
|
||
struct yuv_recv *rec = (struct yuv_recv *)priv;
|
||
u8 type = (p->pixformat == VIDEO_PIX_FMT_YUV444) ? 1 : ((p->pixformat == VIDEO_PIX_FMT_YUV422) ? 2 : 4);
|
||
++rec->yuv_cb_cnt;
|
||
if (!rec->complit) {
|
||
memcpy(rec->y + rec->y_size, p->y, p->width * p->data_height);
|
||
memcpy(rec->u + rec->u_size, p->u, p->width * p->data_height / type);
|
||
memcpy(rec->v + rec->v_size, p->v, p->width * p->data_height / type);
|
||
rec->y_size += p->width * p->data_height;
|
||
rec->u_size += p->width * p->data_height / type;
|
||
rec->v_size += p->width * p->data_height / type;
|
||
rec->recv_size += p->width * p->data_height + (p->width * p->data_height / type) * 2;
|
||
if (rec->recv_size >= rec->size) {
|
||
rec->complit = 1;
|
||
}
|
||
} else {
|
||
printf("err in complit = %d , type = %s \n", rec->complit, (type == 1) ? "YUV444" : (type == 2) ? "yuv422" : "YUV420");
|
||
}
|
||
return 0;
|
||
}
|
||
int avi_unpkg_decoder_to_yuv_example(void)
|
||
{
|
||
int ret;
|
||
char name[64];
|
||
char *fbuf = NULL;
|
||
char *yuv = NULL;
|
||
char *cy, *cb, *cr;
|
||
int fbuflen = 50 * 1024;
|
||
FILE *fd = NULL;
|
||
FILE *yuv_fd = NULL;
|
||
int num = 0;
|
||
int pix;
|
||
char ytype;
|
||
int yuv_len;
|
||
|
||
while (!storage_device_ready()) {//等待sd文件系统挂载完成
|
||
os_time_dly(2);
|
||
}
|
||
|
||
fbuf = malloc(fbuflen);
|
||
if (!fbuf) {
|
||
printf("no men fbuf err!!!\n");
|
||
goto exit;
|
||
}
|
||
sprintf(name, "%sVID_001.AVI", CONFIG_ROOT_PATH);
|
||
//sprintf(name, "%stest1.AVI", CONFIG_ROOT_PATH);
|
||
fd = fopen(name, "r");
|
||
if (!fd) {
|
||
printf("avi file open err : %s !!!\n", name);
|
||
goto exit;
|
||
}
|
||
ret = avi_net_playback_unpkg_init(fd, 1); //解码初始化,最多10分钟视频
|
||
if (ret) {
|
||
printf("avi_net_playback_unpkg_init err!!!\n");
|
||
goto exit;
|
||
}
|
||
redo:
|
||
num = 0;
|
||
while (1) {
|
||
#if 0
|
||
now = timer_get_ms();
|
||
if (last && (now - last) >= 1000) {
|
||
printf("---> sec num = %d \n", num + 1);
|
||
last = now;
|
||
} else if (!last) {
|
||
last = now;
|
||
}
|
||
#endif
|
||
ret = avi_video_get_frame(fd, ++num, fbuf, fbuflen, 1); //全回放功能获取帧
|
||
if (ret > 0) {
|
||
struct jpeg_image_info info = {0};
|
||
struct jpeg_decode_req req = {0};
|
||
u32 *head = (u32 *)fbuf;
|
||
u8 *dec_buf = fbuf;
|
||
u32 fblen = ret;
|
||
if (*head == IDX_00DC || *head == IDX_01WB || *head == IDX_00WB) {
|
||
fblen -= 8;
|
||
dec_buf += 8;
|
||
}
|
||
info.input.data.buf = dec_buf;
|
||
info.input.data.len = fblen;
|
||
if (jpeg_decode_image_info(&info)) {//获取JPEG图片信息
|
||
printf("jpeg_decode_image_info err\n");
|
||
break;
|
||
} else {
|
||
switch (info.sample_fmt) {
|
||
case JPG_SAMP_FMT_YUV444:
|
||
ytype = 1;
|
||
break;//444
|
||
case JPG_SAMP_FMT_YUV420:
|
||
ytype = 4;
|
||
break;//420
|
||
default:
|
||
ytype = 2;
|
||
}
|
||
pix = info.width * info.height;
|
||
yuv_len = pix + pix / ytype * 2;
|
||
if (!yuv) {
|
||
yuv = malloc(yuv_len);
|
||
if (!yuv) {
|
||
printf("yuv malloc err len : %d , width : %d , height : %d \n", yuv_len, info.width, info.height);
|
||
break;
|
||
}
|
||
}
|
||
#if 1
|
||
cy = yuv;
|
||
cb = cy + pix;
|
||
cr = cb + pix / ytype;
|
||
|
||
req.input_type = JPEG_INPUT_TYPE_DATA;
|
||
req.input.data.buf = info.input.data.buf;
|
||
req.input.data.len = info.input.data.len;
|
||
req.buf_y = cy;
|
||
req.buf_u = cb;
|
||
req.buf_v = cr;
|
||
req.buf_width = info.width;
|
||
req.buf_height = info.height;
|
||
req.out_width = info.width;
|
||
req.out_height = info.height;
|
||
req.output_type = JPEG_DECODE_TYPE_DEFAULT;
|
||
req.bits_mode = BITS_MODE_UNCACHE;
|
||
req.dec_query_mode = TRUE;
|
||
|
||
ret = jpeg_decode_one_image(&req);//JPEG转YUV解码
|
||
if (ret) {
|
||
printf("jpeg decode err !!\n");
|
||
break;
|
||
}
|
||
#else
|
||
extern void *jpg_dec_open(struct video_format * f);
|
||
extern int jpg_dec_input_data(void *_fh, void *data, u32 len);
|
||
extern int jpg_dec_set_output_handler(void *_fh, void *priv, int (*handler)(void *, struct YUV_frame_data *));
|
||
extern int jpg_dec_get_s_attr(void *_fh, struct jpg_dec_s_attr * attr);
|
||
extern int jpg_dec_set_s_attr(void *_fh, struct jpg_dec_s_attr * attr);
|
||
struct yuv_recv yuv_rec_data = {0};
|
||
static void *fh = NULL;
|
||
if (!fh) {
|
||
fh = jpg_dec_open(NULL);
|
||
if (!fh) {
|
||
printf("err in jpg_dec_open \n\n");
|
||
return 0;
|
||
}
|
||
struct jpg_dec_s_attr jpg_attr;
|
||
jpg_dec_get_s_attr(fh, &jpg_attr);
|
||
jpg_attr.max_o_width = 320;
|
||
jpg_attr.max_o_height = 240;
|
||
jpg_dec_set_s_attr(fh, &jpg_attr);
|
||
jpg_dec_set_output_handler(fh, (void *)&yuv_rec_data, yuv_out_cb);
|
||
}
|
||
yuv_rec_data.y = yuv;
|
||
yuv_rec_data.u = yuv_rec_data.y + pix;
|
||
yuv_rec_data.v = yuv_rec_data.u + pix / ytype;
|
||
yuv_rec_data.size = yuv_len;
|
||
yuv_rec_data.recv_size = 0;
|
||
yuv_rec_data.y_size = 0;
|
||
yuv_rec_data.u_size = 0;
|
||
yuv_rec_data.v_size = 0;
|
||
yuv_rec_data.complit = 0;
|
||
yuv_rec_data.yuv_cb_cnt = 0;
|
||
ret = jpg_dec_input_data(fh, info.input.data.buf, info.input.data.len);
|
||
if (ret) {
|
||
printf("jpg_dec_input_data waite err \n\n");
|
||
break;
|
||
}
|
||
|
||
if (!yuv_rec_data.complit) {
|
||
printf("yuv_cb_cnt=%d\n", yuv_rec_data.yuv_cb_cnt);
|
||
printf("err yuv_rec_data.complit , size=%d, recv_size=%d\n\n", yuv_rec_data.size, yuv_rec_data.recv_size);
|
||
break;
|
||
}
|
||
|
||
#endif
|
||
|
||
#if AVI_UNPKG_DECODE_TEST
|
||
//写卡例子,可以用软件来验证,当然可以得到YUV之后转RGB可用于显示,例子在jpeg_decode_test.c里的yuv4xxp_quto_rgb565调用方法
|
||
sprintf(name, "%stest.yuv", CONFIG_ROOT_PATH);
|
||
if (!yuv_fd) {
|
||
yuv_fd = fopen(name, "wb+");
|
||
}
|
||
if (yuv_fd) {
|
||
fwrite(yuv_fd, yuv, yuv_len);
|
||
printf("write num = %d \n", num);
|
||
}
|
||
#endif
|
||
}
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
exit:
|
||
avi_net_unpkg_exit(fd, 1);
|
||
#if AVI_UNPKG_DECODE_TEST
|
||
if (yuv_fd) {
|
||
fclose(yuv_fd);
|
||
}
|
||
#endif
|
||
if (fd) {
|
||
fclose(fd);
|
||
}
|
||
if (yuv) {
|
||
free(yuv);
|
||
}
|
||
if (fbuf) {
|
||
free(fbuf);
|
||
}
|
||
return 0;
|
||
}
|
||
int avi_unpkg_example_init(void)
|
||
{
|
||
thread_fork("avi_unpkg_example", 10, 1500, 64, 0, avi_unpkg_decoder_to_yuv_example, NULL);
|
||
return 0;
|
||
}
|
||
#endif
|
||
|
||
#endif
|