2025-06-27 00:32:57 +08:00
|
|
|
|
#include "avi.h"
|
2025-07-06 17:11:38 +08:00
|
|
|
|
#include "dac.h"
|
|
|
|
|
|
#include "ff.h"
|
2025-06-27 00:32:57 +08:00
|
|
|
|
#include "lcd_rgb.h"
|
2025-07-06 17:11:38 +08:00
|
|
|
|
#include "mjpeg.h"
|
2025-06-27 00:32:57 +08:00
|
|
|
|
#include "mymem.h"
|
2025-07-06 17:11:38 +08:00
|
|
|
|
#include "timer.h"
|
|
|
|
|
|
#include "touch_043.h"
|
|
|
|
|
|
#include "usart.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>ѧϰʹ<CFB0>ã<EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD><CEBA><EFBFBD>;
|
|
|
|
|
|
// ALIENTEK STM32F407<30><37><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
// AVI<56><49>Ƶ<EFBFBD><C6B5>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>@ALIENTEK
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̳:www.openedv.com
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:2014/7/20
|
|
|
|
|
|
// <20>汾<EFBFBD><E6B1BE>V1.0
|
|
|
|
|
|
// <20><>Ȩ<EFBFBD><C8A8><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD><D8BE><EFBFBD>
|
|
|
|
|
|
// Copyright(C) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿƼ<D3BF><C6BC><EFBFBD><EFBFBD><EFBFBD>˾ 2009-2019
|
|
|
|
|
|
// All rights reserved
|
2025-06-27 00:32:57 +08:00
|
|
|
|
//*******************************************************************************
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20><EFBFBD><DEB8><EFBFBD>Ϣ
|
|
|
|
|
|
// <20><>
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
AVI_INFO avix; // avi<76>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
|
|
|
|
|
|
u8 *const AVI_VIDS_FLAG_TBL[2] = {"00dc",
|
|
|
|
|
|
"01dc"}; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>,00dc/01dc
|
|
|
|
|
|
u8 *const AVI_AUDS_FLAG_TBL[2] = {"00wb",
|
|
|
|
|
|
"01wb"}; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>,00wb/01wb
|
|
|
|
|
|
|
|
|
|
|
|
static vu8 g_i2splaybuf; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><C5B5><EFBFBD>Ƶ֡<C6B5><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
static u8 *g_i2sbuf[4]; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>֡,<2C><>4֡,4*5K=20K
|
|
|
|
|
|
|
|
|
|
|
|
// <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>I2S DMA<4D><41><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
void audio_i2s_dma_callback(DAC_UserStruct *dac) {
|
|
|
|
|
|
g_i2splaybuf++;
|
|
|
|
|
|
if (g_i2splaybuf > 3)
|
|
|
|
|
|
g_i2splaybuf = 0;
|
|
|
|
|
|
if (dac->buff_useing == 1) {
|
|
|
|
|
|
DMA_MemoryTargetConfig(DMA1_Stream5, (u32)g_i2sbuf[g_i2splaybuf],
|
|
|
|
|
|
DMA_Memory_0);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
DMA_MemoryTargetConfig(DMA1_Stream5, (u32)g_i2sbuf[g_i2splaybuf],
|
|
|
|
|
|
DMA_Memory_1);
|
|
|
|
|
|
}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// avi<76><69><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
|
|
|
|
|
|
// buf:<3A><><EFBFBD>뻺<EFBFBD><EBBBBA><EFBFBD><EFBFBD>
|
|
|
|
|
|
// size:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ֵ:AVI_OK,avi<76>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
AVISTATUS avi_init(u8 *buf, int size) {
|
|
|
|
|
|
u16 offset;
|
|
|
|
|
|
u8 *tbuf;
|
|
|
|
|
|
AVISTATUS res = AVI_OK;
|
|
|
|
|
|
AVI_HEADER *aviheader;
|
|
|
|
|
|
LIST_HEADER *listheader;
|
|
|
|
|
|
AVIH_HEADER *avihheader;
|
|
|
|
|
|
STRH_HEADER *strhheader;
|
|
|
|
|
|
|
|
|
|
|
|
STRF_BMPHEADER *bmpheader;
|
|
|
|
|
|
STRF_WAVHEADER *wavheader;
|
|
|
|
|
|
|
|
|
|
|
|
tbuf = buf;
|
|
|
|
|
|
aviheader = (AVI_HEADER *)buf;
|
|
|
|
|
|
if (aviheader->RiffID != AVI_RIFF_ID)
|
|
|
|
|
|
return AVI_RIFF_ERR; // RIFF ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (aviheader->AviID != AVI_AVI_ID)
|
|
|
|
|
|
return AVI_AVI_ERR; // AVI ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
buf += sizeof(AVI_HEADER); // ƫ<><C6AB>
|
|
|
|
|
|
listheader = (LIST_HEADER *)(buf);
|
|
|
|
|
|
if (listheader->ListID != AVI_LIST_ID)
|
|
|
|
|
|
return AVI_LIST_ERR; // LIST ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (listheader->ListType != AVI_HDRL_ID)
|
|
|
|
|
|
return AVI_HDRL_ERR; // HDRL ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
buf += sizeof(LIST_HEADER); // ƫ<><C6AB>
|
|
|
|
|
|
avihheader = (AVIH_HEADER *)(buf);
|
|
|
|
|
|
if (avihheader->BlockID != AVI_AVIH_ID)
|
|
|
|
|
|
return AVI_AVIH_ERR; // AVIH ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.SecPerFrame = avihheader->SecPerFrame; // <20>õ<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
|
|
|
|
|
avix.TotalFrame = avihheader->TotalFrame; // <20>õ<EFBFBD><C3B5><EFBFBD>֡<EFBFBD><D6A1>
|
|
|
|
|
|
buf += avihheader->BlockSize + 8; // ƫ<><C6AB>
|
|
|
|
|
|
listheader = (LIST_HEADER *)(buf);
|
|
|
|
|
|
if (listheader->ListID != AVI_LIST_ID)
|
|
|
|
|
|
return AVI_LIST_ERR; // LIST ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (listheader->ListType != AVI_STRL_ID)
|
|
|
|
|
|
return AVI_STRL_ERR; // STRL ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
strhheader = (STRH_HEADER *)(buf + 12);
|
|
|
|
|
|
if (strhheader->BlockID != AVI_STRH_ID)
|
|
|
|
|
|
return AVI_STRH_ERR; // STRH ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (strhheader->StreamType == AVI_VIDS_STREAM) // <20><>Ƶ֡<C6B5><D6A1>ǰ
|
|
|
|
|
|
{
|
|
|
|
|
|
if (strhheader->Handler != AVI_FORMAT_MJPG)
|
|
|
|
|
|
return AVI_FORMAT_ERR; // <20><>MJPG<50><47>Ƶ<EFBFBD><C6B5>,<2C><>֧<EFBFBD><D6A7>
|
|
|
|
|
|
avix.VideoFLAG = (u8 *)AVI_VIDS_FLAG_TBL[0]; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "00dc"
|
|
|
|
|
|
avix.AudioFLAG = (u8 *)AVI_AUDS_FLAG_TBL[1]; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "01wb"
|
|
|
|
|
|
bmpheader =
|
|
|
|
|
|
(STRF_BMPHEADER *)(buf + 12 + strhheader->BlockSize + 8); // strf
|
|
|
|
|
|
if (bmpheader->BlockID != AVI_STRF_ID)
|
|
|
|
|
|
return AVI_STRF_ERR; // STRF ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.Width = bmpheader->bmiHeader.Width;
|
|
|
|
|
|
avix.Height = bmpheader->bmiHeader.Height;
|
|
|
|
|
|
buf += listheader->BlockSize + 8; // ƫ<><C6AB>
|
|
|
|
|
|
listheader = (LIST_HEADER *)(buf);
|
|
|
|
|
|
if (listheader->ListID != AVI_LIST_ID) // <20>Dz<EFBFBD><C7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ֡<C6B5><D6A1><EFBFBD><EFBFBD>Ƶ<EFBFBD>ļ<EFBFBD>
|
|
|
|
|
|
{
|
|
|
|
|
|
avix.SampleRate = 0; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.Channels = 0; // <20><>Ƶͨ<C6B5><CDA8><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.AudioType = 0; // <20><>Ƶ<EFBFBD><C6B5>ʽ
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (listheader->ListType != AVI_STRL_ID)
|
|
|
|
|
|
return AVI_STRL_ERR; // STRL ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
strhheader = (STRH_HEADER *)(buf + 12);
|
|
|
|
|
|
if (strhheader->BlockID != AVI_STRH_ID)
|
|
|
|
|
|
return AVI_STRH_ERR; // STRH ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (strhheader->StreamType != AVI_AUDS_STREAM)
|
|
|
|
|
|
return AVI_FORMAT_ERR; // <20><>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>
|
|
|
|
|
|
wavheader =
|
|
|
|
|
|
(STRF_WAVHEADER *)(buf + 12 + strhheader->BlockSize + 8); // strf
|
|
|
|
|
|
if (wavheader->BlockID != AVI_STRF_ID)
|
|
|
|
|
|
return AVI_STRF_ERR; // STRF ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.SampleRate = wavheader->SampleRate; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.Channels = wavheader->Channels; // <20><>Ƶͨ<C6B5><CDA8><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.AudioType = wavheader->FormatTag; // <20><>Ƶ<EFBFBD><C6B5>ʽ
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (strhheader->StreamType == AVI_AUDS_STREAM) // <20><>Ƶ֡<C6B5><D6A1>ǰ
|
|
|
|
|
|
{
|
|
|
|
|
|
avix.VideoFLAG = (u8 *)AVI_VIDS_FLAG_TBL[1]; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "01dc"
|
|
|
|
|
|
avix.AudioFLAG = (u8 *)AVI_AUDS_FLAG_TBL[0]; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "00wb"
|
|
|
|
|
|
wavheader =
|
|
|
|
|
|
(STRF_WAVHEADER *)(buf + 12 + strhheader->BlockSize + 8); // strf
|
|
|
|
|
|
if (wavheader->BlockID != AVI_STRF_ID)
|
|
|
|
|
|
return AVI_STRF_ERR; // STRF ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.SampleRate = wavheader->SampleRate; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.Channels = wavheader->Channels; // <20><>Ƶͨ<C6B5><CDA8><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.AudioType = wavheader->FormatTag; // <20><>Ƶ<EFBFBD><C6B5>ʽ
|
|
|
|
|
|
buf += listheader->BlockSize + 8; // ƫ<><C6AB>
|
|
|
|
|
|
listheader = (LIST_HEADER *)(buf);
|
|
|
|
|
|
if (listheader->ListID != AVI_LIST_ID)
|
|
|
|
|
|
return AVI_LIST_ERR; // LIST ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (listheader->ListType != AVI_STRL_ID)
|
|
|
|
|
|
return AVI_STRL_ERR; // STRL ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
strhheader = (STRH_HEADER *)(buf + 12);
|
|
|
|
|
|
if (strhheader->BlockID != AVI_STRH_ID)
|
|
|
|
|
|
return AVI_STRH_ERR; // STRH ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (strhheader->StreamType != AVI_VIDS_STREAM)
|
|
|
|
|
|
return AVI_FORMAT_ERR; // <20><>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>
|
|
|
|
|
|
bmpheader =
|
|
|
|
|
|
(STRF_BMPHEADER *)(buf + 12 + strhheader->BlockSize + 8); // strf
|
|
|
|
|
|
if (bmpheader->BlockID != AVI_STRF_ID)
|
|
|
|
|
|
return AVI_STRF_ERR; // STRF ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (bmpheader->bmiHeader.Compression != AVI_FORMAT_MJPG)
|
|
|
|
|
|
return AVI_FORMAT_ERR; // <20><>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.Width = bmpheader->bmiHeader.Width;
|
|
|
|
|
|
avix.Height = bmpheader->bmiHeader.Height;
|
|
|
|
|
|
}
|
|
|
|
|
|
offset = avi_srarch_id(tbuf, size, "movi"); // <20><><EFBFBD><EFBFBD>movi ID
|
|
|
|
|
|
if (offset == 0)
|
|
|
|
|
|
return AVI_MOVI_ERR; // MOVI ID<49><44><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (avix.SampleRate) // <20><><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5>,<2C>Ų<EFBFBD><C5B2><EFBFBD>
|
|
|
|
|
|
{
|
|
|
|
|
|
tbuf += offset;
|
|
|
|
|
|
offset = avi_srarch_id(tbuf, size, avix.AudioFLAG); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (offset == 0)
|
|
|
|
|
|
return AVI_STREAM_ERR; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
tbuf += offset + 4;
|
|
|
|
|
|
avix.AudioBufSize = *((u16 *)tbuf); // <20>õ<EFBFBD><C3B5><EFBFBD>Ƶ<EFBFBD><C6B5>buf<75><66>С.
|
|
|
|
|
|
}
|
|
|
|
|
|
// printf("avi init ok\r\n");
|
|
|
|
|
|
// printf("avix.SecPerFrame:%d\r\n",avix.SecPerFrame);
|
|
|
|
|
|
// printf("avix.TotalFrame:%d\r\n",avix.TotalFrame);
|
|
|
|
|
|
// printf("avix.Width:%d\r\n",avix.Width);
|
|
|
|
|
|
// printf("avix.Height:%d\r\n",avix.Height);
|
|
|
|
|
|
// printf("avix.AudioType:%d\r\n",avix.AudioType);
|
|
|
|
|
|
// printf("avix.SampleRate:%d\r\n",avix.SampleRate);
|
|
|
|
|
|
// printf("avix.Channels:%d\r\n",avix.Channels);
|
|
|
|
|
|
// printf("avix.AudioBufSize:%d\r\n",avix.AudioBufSize);
|
|
|
|
|
|
// printf("avix.VideoFLAG:%s\r\n",avix.VideoFLAG);
|
|
|
|
|
|
// printf("avix.AudioFLAG:%s\r\n",avix.AudioFLAG);
|
|
|
|
|
|
return res;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD> ID
|
|
|
|
|
|
// buf:<3A><><EFBFBD>黺<EFBFBD><E9BBBA><EFBFBD><EFBFBD>
|
|
|
|
|
|
// size:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
|
|
|
|
|
|
// id:Ҫ<><D2AA><EFBFBD>ҵ<EFBFBD>id,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>4<EFBFBD>ֽڳ<D6BD><DAB3><EFBFBD>
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ֵ:0,<2C><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>,<2C><><EFBFBD><EFBFBD>:movi IDƫ<44><C6AB><EFBFBD><EFBFBD>
|
|
|
|
|
|
u16 avi_srarch_id(u8 *buf, int size, u8 *id) {
|
|
|
|
|
|
u16 i;
|
|
|
|
|
|
size -= 4;
|
|
|
|
|
|
for (i = 0; i < size; i++) {
|
|
|
|
|
|
if (buf[i] == id[0])
|
|
|
|
|
|
if (buf[i + 1] == id[1])
|
|
|
|
|
|
if (buf[i + 2] == id[2])
|
|
|
|
|
|
if (buf[i + 3] == id[3])
|
|
|
|
|
|
return i; // <20>ҵ<EFBFBD>"id"<22><><EFBFBD>ڵ<EFBFBD>λ<EFBFBD><CEBB>
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20>õ<EFBFBD>stream<61><6D><EFBFBD><EFBFBD>Ϣ
|
|
|
|
|
|
// buf:<3A><><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ַ(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>01wb/00wb/01dc/00dc<64><63>ͷ)
|
|
|
|
|
|
AVISTATUS avi_get_streaminfo(u8 *buf) {
|
|
|
|
|
|
int offset = 0;
|
|
|
|
|
|
avix.StreamID = MAKEWORD(buf + 2); // <20>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
avix.StreamSize = MAKEDWORD(buf + 4); // <20>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>С
|
|
|
|
|
|
if (avix.StreamSize % 2)
|
|
|
|
|
|
avix.StreamSize++; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1(avix.StreamSize,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ż<EFBFBD><C5BC>)
|
|
|
|
|
|
if (avix.StreamID == AVI_VIDS_FLAG || avix.StreamID == AVI_AUDS_FLAG)
|
|
|
|
|
|
return AVI_OK;
|
|
|
|
|
|
return AVI_STREAM_ERR;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-06 17:11:38 +08:00
|
|
|
|
static vu8 g_frame_en = 0;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
2025-07-06 17:11:38 +08:00
|
|
|
|
void avi_timer_irq(void) { g_frame_en = 1; }
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
2025-07-06 17:11:38 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>avix.SecPerFrame
|
|
|
|
|
|
void avi_timer_init(u32 t) {
|
|
|
|
|
|
TIMER_InitStruct timer_init = {0};
|
|
|
|
|
|
timer_init.Cycle = t / 1;
|
|
|
|
|
|
timer_init.Tim = TIM3;
|
|
|
|
|
|
timer_init.UpdataCall = avi_timer_irq;
|
|
|
|
|
|
TIMER_InitNormal(&timer_init);
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-06 17:11:38 +08:00
|
|
|
|
void avi_tiemr_delete(void) { TIMER_DeInit(TIM3); }
|
|
|
|
|
|
|
|
|
|
|
|
#define AVI_AUDIO_BUF_SIZE 1024 * 5 // <20><><EFBFBD><EFBFBD>avi<76><69><EFBFBD><EFBFBD>ʱ,<2C><>Ƶbuf<75><66>С.
|
|
|
|
|
|
#define AVI_VIDEO_BUF_SIZE 1024 * 200 // <20><><EFBFBD><EFBFBD>avi<76><69><EFBFBD><EFBFBD>ʱ,<2C><>Ƶbuf<75><66>С.
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ
|
|
|
|
|
|
int video_play(char *pname, int loop) {
|
|
|
|
|
|
|
|
|
|
|
|
u8 listhead[8] = {0}; // <20><><EFBFBD><EFBFBD>ͷ
|
|
|
|
|
|
u32 fresh = 0;
|
|
|
|
|
|
u8 *framebuf; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>buf
|
|
|
|
|
|
u8 *pbuf; // bufָ<66><D6B8>
|
|
|
|
|
|
FIL *favi;
|
|
|
|
|
|
u8 res = 0;
|
|
|
|
|
|
u16 offset = 0;
|
|
|
|
|
|
UINT nr;
|
|
|
|
|
|
u8 key;
|
|
|
|
|
|
u8 i2ssavebuf;
|
|
|
|
|
|
DAC_UserStruct dac = {0};
|
|
|
|
|
|
|
|
|
|
|
|
u8 *audio_buff = mymalloc(AVI_AUDIO_BUF_SIZE);
|
|
|
|
|
|
framebuf = mymalloc(AVI_VIDEO_BUF_SIZE); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶbuf
|
|
|
|
|
|
favi = (FIL *)mymalloc(sizeof(FIL)); // <20><><EFBFBD><EFBFBD>favi<76>ڴ<EFBFBD>
|
|
|
|
|
|
g_i2sbuf[0] = mymalloc(AVI_AUDIO_BUF_SIZE); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ڴ<EFBFBD>
|
|
|
|
|
|
g_i2sbuf[1] = mymalloc(AVI_AUDIO_BUF_SIZE); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ڴ<EFBFBD>
|
|
|
|
|
|
g_i2sbuf[2] = mymalloc(AVI_AUDIO_BUF_SIZE); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ڴ<EFBFBD>
|
|
|
|
|
|
g_i2sbuf[3] = mymalloc(AVI_AUDIO_BUF_SIZE); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ڴ<EFBFBD>
|
|
|
|
|
|
mymemset(g_i2sbuf[0], 0, AVI_AUDIO_BUF_SIZE);
|
|
|
|
|
|
mymemset(g_i2sbuf[1], 0, AVI_AUDIO_BUF_SIZE);
|
|
|
|
|
|
mymemset(g_i2sbuf[2], 0, AVI_AUDIO_BUF_SIZE);
|
|
|
|
|
|
mymemset(g_i2sbuf[3], 0, AVI_AUDIO_BUF_SIZE);
|
|
|
|
|
|
while (res == 0) {
|
|
|
|
|
|
res = f_open(favi, (char *)pname, FA_READ);
|
|
|
|
|
|
if (res == 0) {
|
|
|
|
|
|
pbuf = framebuf;
|
|
|
|
|
|
res = f_read(favi, pbuf, AVI_VIDEO_BUF_SIZE, &nr); // <20><>ʼ<EFBFBD><CABC>ȡ
|
|
|
|
|
|
if (res) {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
// <20><>ʼavi<76><69><EFBFBD><EFBFBD>
|
|
|
|
|
|
res = avi_init(pbuf, AVI_VIDEO_BUF_SIZE); // avi<76><69><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (res) {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
// avi_timer_init (avix.SecPerFrame);
|
|
|
|
|
|
offset =
|
|
|
|
|
|
avi_srarch_id(pbuf, AVI_VIDEO_BUF_SIZE, (u8 *)"movi"); // Ѱ<><D1B0>movi ID
|
|
|
|
|
|
avi_get_streaminfo(pbuf + offset + 4); // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ϣ
|
|
|
|
|
|
f_lseek(favi, offset + 12 - 8); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־ID,<2C><><EFBFBD><EFBFBD>ַƫ<D6B7>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD>ʼ<EFBFBD><CABC>
|
|
|
|
|
|
extern void jdmerge_setvideo_xsize(int xsize, int lcd_xsize);
|
|
|
|
|
|
jdmerge_setvideo_xsize(avix.Width, LCD_GetLcdSizeX()); // <20><><EFBFBD>õ<EFBFBD>ַ<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
res =
|
|
|
|
|
|
mjpegdec_init((LCD_GetLcdSizeX() - avix.Width) / 2,
|
|
|
|
|
|
(LCD_GetLcdSizeY() - avix.Height) / 2); // JPG<50><47><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>
|
|
|
|
|
|
if (avix.SampleRate) // <20><><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5>Ϣ,<2C>ų<EFBFBD>ʼ<EFBFBD><CABC>
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><>ʼ<EFBFBD><CABC>DAC
|
|
|
|
|
|
dac.buff1 = (u32 *)g_i2sbuf[1];
|
|
|
|
|
|
dac.buff2 = (u32 *)g_i2sbuf[2];
|
|
|
|
|
|
dac.buff_size = avix.AudioBufSize;
|
|
|
|
|
|
dac.rate = DAC_GetRate(avix.SampleRate);
|
|
|
|
|
|
dac.call_back = audio_i2s_dma_callback;
|
|
|
|
|
|
DAC_NormalInit(&dac);
|
|
|
|
|
|
}
|
|
|
|
|
|
while (1) // <20><><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>
|
|
|
|
|
|
{
|
|
|
|
|
|
f_read(favi, listhead, 8, &nr);
|
|
|
|
|
|
if (avi_get_streaminfo(listhead)) // <20><>ȡ<EFBFBD><C8A1>һ֡ <20><><EFBFBD><EFBFBD>־
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (Touch_GetState()->x[1] != 0)
|
|
|
|
|
|
break; // <20><>Ļ<EFBFBD><C4BB><EFBFBD>㴥<EFBFBD><E3B4A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (USART3_GetKeyPressed() & (0x08))
|
|
|
|
|
|
break; // <20><><EFBFBD>·<EFBFBD><C2B7>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (avix.StreamID == AVI_VIDS_FLAG) // <20><>Ƶ<EFBFBD><C6B5>
|
|
|
|
|
|
{
|
|
|
|
|
|
pbuf = framebuf;
|
|
|
|
|
|
// mymemset (pbuf,0,AVI_VIDEO_BUF_SIZE);
|
|
|
|
|
|
f_read(favi, pbuf, avix.StreamSize + 8 - 8,
|
|
|
|
|
|
&nr); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡+<2B><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID<49><44>Ϣ
|
|
|
|
|
|
// <20>ȴ<EFBFBD>֡ʱ<D6A1><CAB1>
|
|
|
|
|
|
// while (g_frame_en==0){} g_frame_en=0;
|
|
|
|
|
|
while (LCD_GetLayerUpdataStat() == 0)
|
|
|
|
|
|
;
|
|
|
|
|
|
LCD_SwitchLayerBuff();
|
|
|
|
|
|
res = mjpegdec_decode(pbuf, avix.StreamSize);
|
|
|
|
|
|
if (res == 0) {
|
|
|
|
|
|
LCD_ExitLayerBuff();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (res) {
|
|
|
|
|
|
// break;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else // <20><>Ƶ<EFBFBD><C6B5>
|
|
|
|
|
|
{
|
|
|
|
|
|
// f_read(favi,audio_buff,avix.StreamSize+8-8,&nr);//<2F><><EFBFBD><EFBFBD>i2sbuf
|
|
|
|
|
|
// pbuf=audio_buff;
|
|
|
|
|
|
i2ssavebuf++;
|
|
|
|
|
|
if (i2ssavebuf > 3)
|
|
|
|
|
|
i2ssavebuf = 0;
|
|
|
|
|
|
do {
|
|
|
|
|
|
nr = g_i2splaybuf;
|
|
|
|
|
|
if (nr)
|
|
|
|
|
|
nr--;
|
|
|
|
|
|
else
|
|
|
|
|
|
nr = 3;
|
|
|
|
|
|
} while (i2ssavebuf == nr); // <20><>ײ<EFBFBD>ȴ<EFBFBD>.
|
|
|
|
|
|
f_read(favi, g_i2sbuf[i2ssavebuf], avix.StreamSize,
|
|
|
|
|
|
&nr); // <20><><EFBFBD><EFBFBD>i2sbuf
|
|
|
|
|
|
u16 *p = (u16 *)g_i2sbuf[i2ssavebuf];
|
|
|
|
|
|
for (int i = 0; i < avix.StreamSize / 2; i++)
|
|
|
|
|
|
p[i] = (p[i] + 0x8000) >> 4;
|
|
|
|
|
|
pbuf = g_i2sbuf[i2ssavebuf];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// avi_tiemr_delete();
|
|
|
|
|
|
mjpegdec_free(); // <20>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
|
|
|
|
|
|
f_close(favi);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (loop == 0)
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
myfree(framebuf);
|
|
|
|
|
|
myfree(favi);
|
|
|
|
|
|
myfree(audio_buff);
|
|
|
|
|
|
myfree(g_i2sbuf[0]);
|
|
|
|
|
|
myfree(g_i2sbuf[1]);
|
|
|
|
|
|
myfree(g_i2sbuf[2]);
|
|
|
|
|
|
myfree(g_i2sbuf[3]);
|
|
|
|
|
|
DAC_NormalDeInit(&dac);
|
|
|
|
|
|
return (int)res;
|
|
|
|
|
|
}
|