#include #include #include #include "openDML.h" #include "osal/string.h" extern bool stdidx_write2disk(bool type,void *f,uint32 num,ODMLBUFF *buff,void *f_write); //一些未移植的宏控制 #define FATFS_OPENDML 1 static uint8 headerbuf[_ODML_AVI_HEAD_SIZE__]; /************************************************************** * name :ODMLSync * funtion :write back infomation to AVIX and file head in recore avi /* ***********************************************************/ int ODMLSync(volatile void* file,ODMLBUFF *buff,bool Enpcm,uint32_t (*osal_fwrite) (void *, uint32_t , uint32_t , F_FILE *)) { //uint32 writed; uint32 *ptemp; //uint32 sector; int ret; ODMLAVIFILEHEADER *aviheader = (ODMLAVIFILEHEADER *)buff->sync_buf;//(ODMLAVIFILEHEADER *) headerbuf; //************AVIX updata************** short i; //uint32 br; //updata last AVIX if(buff->AVIXnum > -1){ buff->movlist[buff->AVIXnum].riff.cb = osal_fsize((F_FILE *)file) - buff->moviofest[buff->AVIXnum] - 8 ;//list riff size buff->movlist[buff->AVIXnum].movi.cb = osal_fsize((F_FILE *)file) - buff->moviofest[buff->AVIXnum] - 20;//list movi size } //write back AVIX size for(i = 0; i < 1+buff->AVIXnum ; i++ ){ ret=osal_fseek((F_FILE *)file,buff->moviofest[i] ); ret= (*osal_fwrite)((void*)&buff->movlist[i],1,sizeof(AVIXMOVILIST),(F_FILE *)file); if(ret != FR_OK) { _os_printf("rewrite_AVIX err\n"); } } //***************************************** //=========fill avifileheader info========= if(buff->AVIXnum > -1){ aviheader->riff.cb = buff->moviofest[0] -8;//point to RIFF then cut list.fcc and list.cb aviheader->avih.dwTotalFrames =buff->avilisframecnt; // } else{ aviheader->riff.cb = osal_fsize((F_FILE *)file)-8;//g_stcJpegInfo.dwIndexLen + g_stcJpegInfo.dwChunkLen - 8; aviheader->avih.dwTotalFrames =buff->vframecnt; // } aviheader->strh_v.dwLength = buff->vframecnt;// if(Enpcm) aviheader->strh_a.dwLength = buff->aframecnt*(buff->aframeSample)/2; else aviheader->strh_a.dwLength = 0; //********************super indx****************** aviheader->vsupindxh.nEntriesInUse = buff->svidxcount; aviheader->asupindxh.nEntriesInUse = buff->saidxcount; memcpy(aviheader->aindx,buff->asuperindx,sizeof(superindx)*buff->saidxcount); memcpy(aviheader->vindx,buff->vsuperindx,sizeof(superindx)*buff->svidxcount); aviheader->strodml.dwTotalFrames = buff->vframecnt + aviheader->strh_a.dwLength; if(!Enpcm){ //memset(aviheader->aindx,0,sizeof(superindx)*buff->saidxcount); aviheader->asupindxh.nEntriesInUse = 0; } //***********************"movi"***************************** ptemp = (uint32*)((uint32)aviheader+_ODML_AVI_HEAD_SIZE__-12); //data block head ptemp[0] = 0x5453494c; //"LIST" if(buff->AVIXnum > -1) ptemp[1]=buff->moviofest[0] -_ODML_AVI_HEAD_SIZE__+4; else ptemp[1] = osal_fsize((F_FILE *)file) -_ODML_AVI_HEAD_SIZE__+4; // ptemp[2] = 0x69766f6d; //"movi" //=========write avifileheader info======= ret = osal_fseek((F_FILE *)file, 0); ret = (*osal_fwrite)((void *)aviheader,1,_ODML_AVI_HEAD_SIZE__,(F_FILE *)file); if(ret != _ODML_AVI_HEAD_SIZE__) { _os_printf("avi update hd err\n"); return false; } return true; } uint32 get_curofset(void *f) { return osal_ftell(f); } void OdmlSyncAVIInfo(void *f,ODMLBUFF *buff,bool Enpcm) { buff->fileofset = get_curofset(f); #ifdef SECTOR_SYNC ODMLSync_Sector(f,buff,&buff->Sync_buff,Enpcm,osal_fwrite); #else ODMLSync(f,buff,Enpcm,osal_fwrite); #endif osal_fseek(f,buff->fileofset); f_sync(f); } void stdindx_updata(void *f,ODMLBUFF *buff) { #if FATFS_OPENDML //video stdindx stdidx_write2disk(0,f,buff->vidxcount,buff,osal_fwrite); //audo stdindx stdidx_write2disk(1,f,buff->aidxcount,buff,osal_fwrite); #else //video stdindx stdidx_write2disk(0,f,buff->vidxcount,buff,NULL); //audo stdindx stdidx_write2disk(1,f,buff->aidxcount,buff,NULL); #endif } int ODMLUpdateAVIInfo(void * file,ODMLBUFF *buff,bool Enpcm,void *f_write,ODMLAVIFILEHEADER * headerbuf) { uint32 *ptemp; int ret; ODMLAVIFILEHEADER *aviheader = headerbuf; /************AVIX updata**************/ short i; //updata last AVIX if(buff->AVIXnum > -1){ #if FATFS_OPENDML buff->movlist[buff->AVIXnum].riff.cb = osal_fsize(file) - buff->moviofest[buff->AVIXnum] - 8 ;//list riff size buff->movlist[buff->AVIXnum].movi.cb = osal_fsize(file) - buff->moviofest[buff->AVIXnum] - 20;//list movi size #endif } //write back AVIX size _os_printf("%s:%d\tavixnum:%d\n",__FUNCTION__,__LINE__,buff->AVIXnum); for(i = 0; i < 1+buff->AVIXnum ; i++ ){ #if FATFS_OPENDML ret= osal_fseek(file,buff->moviofest[i] ); ret= osal_fwrite(&buff->movlist[i],1,sizeof(AVIXMOVILIST),file); #endif if(ret != sizeof(AVIXMOVILIST)) { _os_printf("rewrite_AVIX err\n"); } } _os_printf("rewrite_AVIX end\n"); /*****************************************/ memset(aviheader,0,_ODML_AVI_HEAD_SIZE__); //=========fill avifileheader info========= #if FATFS_OPENDML ret = osal_fseek(file, 0); ret = osal_fread((void *)aviheader,1,_ODML_AVI_HEAD_SIZE__,file); #endif if(buff->AVIXnum > -1){ aviheader->riff.cb = buff->moviofest[0] -8;//point to RIFF then cut list.fcc and list.cb aviheader->avih.dwTotalFrames =buff->avilisframecnt; // } else{ #if FATFS_OPENDML aviheader->riff.cb = osal_fsize(file)-8;// #endif aviheader->avih.dwTotalFrames =buff->vframecnt; // } aviheader->strh_v.dwLength = buff->vframecnt;// if(Enpcm) aviheader->strh_a.dwLength = buff->aframecnt*(buff->aframeSample)/2; //aviheader->strh_a.dwLength = buff->aframecnt*(PCM_SHEET_SIZE-8); else aviheader->strh_a.dwLength = 0; /********************super indx********************/ aviheader->vsupindxh.nEntriesInUse = buff->svidxcount; aviheader->asupindxh.nEntriesInUse = buff->saidxcount; memcpy(aviheader->aindx,buff->asuperindx,sizeof(superindx)*buff->saidxcount); memcpy(aviheader->vindx,buff->vsuperindx,sizeof(superindx)*buff->svidxcount); aviheader->strodml.dwTotalFrames = buff->vframecnt + aviheader->strh_a.dwLength; if(!Enpcm){ //这里应该填什么?原来这里代码应该是有错的,暂时先去掉,为什么之前录卡没有出现问题?memset? //memcpy(aviheader->aindx,0,sizeof(superindx)*buff->saidxcount); aviheader->asupindxh.nEntriesInUse = 0; } /***********************"movi"*****************************/ ptemp = (uint32*)((uint32)aviheader+_ODML_AVI_HEAD_SIZE__-12); //data block head ptemp[0] = 0x5453494c; //"LIST" if(buff->AVIXnum > -1) ptemp[1]=buff->moviofest[0] -_ODML_AVI_HEAD_SIZE__+4; else { #if FATFS_OPENDML ptemp[1] = osal_fsize(file) -_ODML_AVI_HEAD_SIZE__+4; #endif } ptemp[2] = 0x69766f6d; //"movi" //debgbuf(headerbuf, 512); //=========write avifileheader info======= #if FATFS_OPENDML ret = osal_fseek(file, 0); ret = osal_fwrite((void *)aviheader,1,_ODML_AVI_HEAD_SIZE__,file); #else ret = _ODML_AVI_HEAD_SIZE__; #endif if(ret != _ODML_AVI_HEAD_SIZE__) { _os_printf("avi update hd err\n"); return false; } _os_printf("osal_fwrite:ret =%d\n",ret); return true; } void ODMLbuff_init(ODMLBUFF *buff) { memset((void *)buff,0,sizeof(ODMLBUFF)); buff->AVIXnum = -1; buff->qwOffset = _ODML_AVI_HEAD_SIZE__ - 4;//point to first movi } /**************************************************************************** * name :supindxbuff_updata * funtion :should record stdinx infomation when the stdindx wirte to disk * this funtion just write data to buff not to disk * ************************************************************************/ bool supindxbuff_updata(bool typ,uint64 ofset,uint32 size,uint32 packnum,ODMLBUFF *buff) { if(typ) { buff->asuperindx[buff->saidxcount].qwOffset = ofset; buff->asuperindx[buff->saidxcount].dwSize = size; //buff->asuperindx[buff->saidxcount].dwDuration = packnum; buff->asuperindx[buff->saidxcount].dwDuration = packnum*(buff->aframeSample)/2; //_os_printf("packnum:%d\tdwDuration:%d\r\n",packnum,buff->asuperindx[buff->saidxcount].dwDuration); #if 0 if(buff->Sync_buff.asupindx_count == 32) { buff->Sync_buff.asupindx_count = 0; memset(&buff->Sync_buff.asupidx,0,512); buff->Sync_buff.asupidx_sector ++; } buff->Sync_buff.asupidx.Aindx[buff->Sync_buff.asupindx_count].qwOffset= ofset; buff->Sync_buff.asupidx.Aindx[buff->Sync_buff.asupindx_count].dwSize= size; buff->Sync_buff.asupidx.Aindx[buff->Sync_buff.asupindx_count].dwDuration= packnum*(PCM_SHEET_SIZE-8)/2; buff->Sync_buff.asupindx_count ++; #endif buff->saidxcount++; if(buff->saidxcount == SupIDXBUFLEN-1) { _os_printf("supindxbuff full\n"); return false; } } else { buff->vsuperindx[buff->svidxcount].qwOffset = ofset; buff->vsuperindx[buff->svidxcount].dwSize =size; buff->vsuperindx[buff->svidxcount].dwDuration = packnum; #if 0 if(buff->Sync_buff.vsupindx_count == 32) { buff->Sync_buff.vsupindx_count = 0; memset(&buff->Sync_buff.vsupidx,0,512); buff->Sync_buff.vsupidx_sector++; } buff->Sync_buff.vsupidx.vindx[buff->Sync_buff.vsupindx_count].qwOffset= ofset; buff->Sync_buff.vsupidx.vindx[buff->Sync_buff.vsupindx_count].dwSize= size; buff->Sync_buff.vsupidx.vindx[buff->Sync_buff.vsupindx_count].dwDuration= packnum; buff->Sync_buff.vsupindx_count ++; #endif buff->svidxcount++; if(buff->svidxcount == SupIDXBUFLEN-1) { _os_printf("supindxbuff full\n"); return false; } } return true; } //uint32 junk[128]; #if 0 void add_AVIX( void *f,uint64 fileoffest,ODMLBUFF *buff,void *f_write) { uint32 br; uint32 fillsize; uint32 junk[2]; buff -> AVIXnum ++;//record how many AVIX it has if(buff -> AVIXnum == AVIXMAXNUM ){ buff -> AVIXnum =0; _os_printf("Add AVIX error!!! \n"); } buff -> movlist[buff -> AVIXnum].riff.fcc = 0x46464952;//RIFF buff -> movlist[buff -> AVIXnum].riff.cb = 0;//size buff -> movlist[buff -> AVIXnum].riff.fcctype = 0X58495641;//AVIX buff -> movlist[buff -> AVIXnum].movi.fcc = 0x5453494c;//LIST buff -> movlist[buff -> AVIXnum].movi.cb = 0;//size buff -> movlist[buff -> AVIXnum].movi.fcctype = 0x69766f6d;//movi #if FATFS_OPENDML osal_fwrite( &buff -> movlist[buff -> AVIXnum], 1,sizeof(AVIXMOVILIST),f); #endif fillsize =512-(br%512); if(fillsize != 512 ){ //_os_printf("fill size:%d",fillsize); //memset((void *)junk,0,512); junk[0] = 0x4b4e554a;//junk junk[1] = fillsize-8; #if FATFS_OPENDML osal_fwrite ((void*)&junk,1, 8,f); osal_fseek(f,osal_ftell(f)+fillsize-8); #endif } buff ->moviofest[buff -> AVIXnum] = fileoffest; buff ->qwOffset = fileoffest+20;//fileoffest point to RIFF qwOffset should point to "movi" if(buff -> AVIXnum > 0){//more then one AVIX buff ->movlist[buff -> AVIXnum-1].riff.cb = fileoffest - buff ->moviofest[buff -> AVIXnum-1]-8 ;//list riff size buff ->movlist[buff -> AVIXnum-1].movi.cb = fileoffest - buff ->moviofest[buff -> AVIXnum-1]-20;//list movi size } } #endif #if SYNC_EN void init_Syncbuff(ODMLAVI_SECTOR *buff,void *file){ FIL* fp; fp = file; ODMLAVIFILEHEADER *head = (ODMLAVIFILEHEADER *)headerbuf; uint32 start_sector =clust2sect(fp->obj.fs,fp->obj.sclust); uint32 supindx_secnum; memcpy(&buff->video,head,512); memcpy(&buff->auds,&head->strl_a,512); memcpy(&buff->movi,&head->obml,512); buff->video_sector = start_sector; buff->vsupidx_sector = start_sector+1; supindx_secnum = (SUPERIDXLEN*sizeof(superindx)+(512-(SUPERIDXLEN*16)%512))/512; buff->auds_sector = start_sector+supindx_secnum+2; buff->asupidx_sector = start_sector+supindx_secnum+3; buff->movi_sector = start_sector+2*supindx_secnum+3; buff->asupindx_count = 0; buff->vsupindx_count = 0; } #endif /************************************************************** * name :OMDLvideo_header_write * funtion :write the OpenDML AVI file * ***********************************************************/ int OMDLvideo_header_write(void *f_write,void *f, AVI_INFO *msg,ODMLAVIFILEHEADER *headerbuf) { uint32_t ret; ODMLAVIFILEHEADER *aviheader = headerbuf; memset((void *)aviheader,0,_ODML_AVI_HEAD_SIZE__); if(msg->pcm){ //fill strl audqs aviheader->strl_a.fcc = 0x5453494c; //"LIST" aviheader->strl_a.cb = 888-(SUPERIDXLEN*16)%512 +sizeof(aviheader->strl_a.fcctype)+2*sizeof(CHUNK)+sizeof(AVISTREAMHEADER)+sizeof(AVIWAVEFORMATEX) + sizeof(AVISUPERINDEXHEAD)+SUPERIDXLEN*sizeof(superindx); aviheader->strl_a.fcctype = 0x6c727473; //"strl" //fill auds stream aviheader->strh_a.fcc = 0x68727473; //"strh" aviheader->strh_a.cb = sizeof(AVISTREAMHEADER)-8; aviheader->strh_a.fccType = 0x73647561; //"auds" aviheader->strh_a.dwScale = 2;//4 aviheader->strh_a.dwRate = msg->audiofrq << 1; aviheader->strh_a.dwLength = 1024;//2048; aviheader->strh_a.dwSampleSize = 2;//4 aviheader->strh_a.dwSuggestedBufferSize=0x00010000; // aviheader->strh_a.dwQuality =0xFFFFFFFF; //fill auds stream info aviheader->strf_a.dwFourCC = 0x66727473; //"strf" aviheader->strf_a.dwSize = sizeof(AVIWAVEFORMATEX); aviheader->wavinfo.wFormatTag = 1; //1:pcm 2:adpcm aviheader->wavinfo.nChannels = 1;//2 aviheader->wavinfo.nSamplesPerSec = msg->audiofrq; //11025 , 22050, 44100 aviheader->wavinfo.nAvgBytesPerSec = msg->audiofrq << 1;//64000 aviheader->wavinfo.nBlockAlign = 2; //4 // ch*bitspersample /8 aviheader->wavinfo.wBitsPerSample = 16; //auds superindx aviheader->sidx_a.dwFourCC = 0x78646e69; //"indx" aviheader->sidx_a.dwSize = sizeof(AVISUPERINDEXHEAD)+sizeof(superindx)*SUPERIDXLEN; aviheader->asupindxh.dwChunkId = 0x62773130; //"01wb" aviheader->asupindxh.wLongsPerEntry=4;//4 aviheader->asupindxh.bIndexSubType=0; // must be 0 or AVI_INDEX_2FIELD aviheader->asupindxh.bIndexType=AVI_INDEX_OF_INDEXES; // must be AVI_INDEX_OF_INDEXES aviheader->asupindxh.nEntriesInUse=0;//4 aviheader->asupindxh.dwReserved[0]=0;//0 aviheader->asupindxh.dwReserved[1]=0;//0 aviheader->asupindxh.dwReserved[2]=0;//0 //fill junk aviheader->junk.dwFourCC= 0x4b4e554a; //"JUNK" aviheader->junk.dwSize= _ODML_AVI_HEAD_SIZE__ - (sizeof(ODMLAVIFILEHEADER) + 12); } else{ aviheader->strl_a.fcc = 0x4b4e554a; //"JUNK" aviheader->strl_a.cb = 888-(SUPERIDXLEN*16)%512 +sizeof(aviheader->strl_a.fcctype)+2*sizeof(CHUNK)+sizeof(AVISTREAMHEADER)+sizeof(AVIWAVEFORMATEX) + sizeof(AVISUPERINDEXHEAD)+SUPERIDXLEN*sizeof(superindx); //fill junk aviheader->junk.dwFourCC= 0x4b4e554a; //"JUNK" aviheader->junk.dwSize= _ODML_AVI_HEAD_SIZE__ - (sizeof(ODMLAVIFILEHEADER) + 12); } //fill fcc and fcc type aviheader->riff.fcc = 0x46464952; //"RIFF" aviheader->riff.fcctype = 0x20495641; //"AVI " aviheader->hdrl.fcc = 0x5453494c; //"LIST" aviheader->hdrl.cb =_ODML_AVI_HEAD_SIZE__ - 12 - 8-12; //aviheader->hdrl.cb =sizeof(AVIFILEHEADER) - 28; //point to junk in end of head aviheader->hdrl.fcctype = 0x6c726468; //"hdrl" //fill avimainheader aviheader->avih.fcc = 0x68697661; //"avih" aviheader->avih.cb = sizeof(AVIMAINHEADER)-8; aviheader->avih.dwMicroSecPerFrame = 0x8235; // 30fps ,so (1s/30)*1000*1000 = 33333us aviheader->avih.dwFlags = AVIF_HASINDEX|AVIF_MUSTUSEINDEX; //has index aviheader->strh_v.dwSuggestedBufferSize=0x00100000; aviheader->avih.dwStreams = 0x1 + msg->pcm; aviheader->avih.dwWidth = msg->win_w; //640 aviheader->avih.dwHeight = msg->win_h;;//480 //file move fcc and fcc type aviheader->strl_v.fcc = 0x5453494c; //"LIST" aviheader->strl_v.cb = sizeof(aviheader->strl_v.fcctype) + 3*sizeof(CHUNK)+sizeof(AVISTREAMHEADER)+sizeof(AVIBITMAPINFOHEADER) + sizeof(VideoPropHeader) +sizeof(AVISUPERINDEXHEAD)+SUPERIDXLEN*sizeof(superindx) +1216-(SUPERIDXLEN*16)%512; aviheader->strl_v.fcctype = 0x6c727473; //"strl" aviheader->strh_v.fcc = 0x68727473; //"strh" aviheader->strh_v.cb = sizeof(AVISTREAMHEADER)-8; aviheader->strh_v.fccType = 0x73646976; //"vids" aviheader->strh_v.fccHandler = 0x47504a4d; //"MJPG" aviheader->strh_v.dwScale = 1; aviheader->strh_v.dwRate = 30; aviheader->strh_v.dwStart = 0; aviheader->strh_v.rcFrame.right =msg->win_w; aviheader->strh_v.rcFrame.bottom = msg->win_h;//480 //fill vids stream info aviheader->strf_v.dwFourCC = 0x66727473; //"strf" aviheader->strf_v.dwSize = sizeof(AVIBITMAPINFOHEADER); aviheader->bitmapinfo.biSize = sizeof(AVIBITMAPINFOHEADER); aviheader->bitmapinfo.biWidth = msg->win_w; //640 aviheader->bitmapinfo.biHeight = msg->win_h;//480 aviheader->bitmapinfo.biPlanes = 1; // always 1 aviheader->bitmapinfo.biBitCount = 24; // 1, 4, 8, 16, 24, 32 aviheader->bitmapinfo.biCompression = 0x47504a4d; //"MJPG" aviheader->strh_v.dwSuggestedBufferSize=0x00100000; // aviheader->strh_v.dwQuality =0xFFFFFFFF; //video superindx aviheader->sidx_v.dwFourCC = 0x78646e69; //"indx" aviheader->sidx_v.dwSize = sizeof(AVISUPERINDEXHEAD)+sizeof(superindx)*SUPERIDXLEN; _os_printf("dw:%X\t%X\t%X\t%X\n",(int)aviheader->sidx_v.dwSize,sizeof(AVISUPERINDEXHEAD),sizeof(superindx),SUPERIDXLEN); aviheader->vsupindxh.dwChunkId = 0x63643030; //"00dc" aviheader->vsupindxh.wLongsPerEntry=4;//4 aviheader->vsupindxh.bIndexSubType=0; // must be 0 or AVI_INDEX_2FIELD aviheader->vsupindxh.bIndexType=AVI_INDEX_OF_INDEXES; // must be AVI_INDEX_OF_INDEXES aviheader->vsupindxh.nEntriesInUse=0;//4 aviheader->vsupindxh.dwReserved[0]=0;//0 aviheader->vsupindxh.dwReserved[1]=0;//0 aviheader->vsupindxh.dwReserved[2]=0;//0 //Video Properties Header aviheader->c_vprp.dwFourCC=0x70727076; //"vprp" aviheader->c_vprp.dwSize = sizeof(VideoPropHeader); aviheader->vprp.dwFrameWidthInPixels=msg->win_w; aviheader->vprp.dwFrameHeightInLines=msg->win_h; aviheader->vprp.dwHTotalInT = msg->win_w; aviheader->vprp.dwVTotalInLines=msg->win_h; aviheader->vprp.dwVerticalRefreshRate=30; aviheader->vprp.dwFrameAspectRatio=0x00100009; aviheader->vprp.VideoFormatToken=0; aviheader->vprp.VideoStandard=0; aviheader->vprp.nbFieldPerFrame =1; aviheader->vprp.FieldInfo.CompressedBMHeight=msg->win_h; aviheader->vprp.FieldInfo.CompressedBMWidth=msg->win_w; aviheader->vprp.FieldInfo.ValidBMHeight=msg->win_h; aviheader->vprp.FieldInfo.ValidBMWidth=msg->win_w; aviheader->vprp.FieldInfo.ValidBMXOffset=0; aviheader->vprp.FieldInfo.ValidBMYOffset=0; aviheader->vprp.FieldInfo.VideoXOffsetInT=0; aviheader->vprp.FieldInfo.VideoYValidStartLine=0; //Extended AVI Header (dmlh) aviheader->obml.fcc=0x5453494c; //"LIST" aviheader->obml.cb=sizeof(ODMLExtendedAVIHeader) + sizeof(aviheader->obml.fcctype); aviheader->obml.fcctype =0x6c6d646f; //"odml" aviheader->strodml.OpenDML_Header=0x686c6d64; //"dmlh" aviheader->strodml.size = sizeof(ODMLExtendedAVIHeader)-8; aviheader->strodml.dwTotalFrames=0; //"TotalFrame" /****************secotor junk fill******************/ aviheader->sector1_junk.dwFourCC= 0x4b4e554a; aviheader->sector1_junk.dwSize=260; aviheader->sector2_junk.dwFourCC= 0x4b4e554a; aviheader->sector2_junk.dwSize=512-(SUPERIDXLEN*16)%512 - 8; aviheader->sector3_junk.dwFourCC= 0x4b4e554a; aviheader->sector3_junk.dwSize=428; aviheader->sector4_junk.dwFourCC= 0x4b4e554a; aviheader->sector4_junk.dwSize=368; aviheader->sector5_junk.dwFourCC= 0x4b4e554a; aviheader->sector5_junk.dwSize=512-(SUPERIDXLEN*16)%512 - 8; //_os_printf("j1:%X\tj2:%X\tj3:%X\tj4:%X\tj5:%X\n",aviheader->sector1_junk.dwSize,aviheader->sector2_junk.dwSize,aviheader->sector3_junk.dwSize,aviheader->sector4_junk.dwSize,aviheader->sector5_junk.dwSize); /*****************************************************/ _os_printf("VIDEO REC :file head size %d \n",_ODML_AVI_HEAD_SIZE__); #if FATFS_OPENDML ret = osal_fwrite(headerbuf,1, _ODML_AVI_HEAD_SIZE__,f); // 4K AVI head if(ret != _ODML_AVI_HEAD_SIZE__) { _os_printf("vai -w hd err\n"); return -1; } #endif //_os_printf("header ok\n"); return 1; } //uint32 junk[128]; bool stdidx_write2disk(bool type,void *f,uint32 num,ODMLBUFF *buff,void *f_write) { uint32 junk[2]; uint64 stdofset=0; uint32 size=0; uint32 fillsize=0; uint64 *p64; AVISTDINDEXHEAD stdindxhead; int ret = 0; memset((void *)&stdindxhead,0,sizeof(AVISTDINDEXHEAD)); size = sizeof(stdindx)*num + sizeof(AVISTDINDEXHEAD) ; if(num==0)return true; //size = sizeof(stdindx)*num; stdindxhead.wLongsPerEntry = 2; stdindxhead.bIndexSubType=0; //stdindxhead.dwReserved= 0; stdindxhead.bIndexType= AVI_INDEX_OF_CHUNKS; stdindxhead.cb = sizeof(AVISTDINDEXHEAD)-8+sizeof(stdindx)*num; p64 = (uint64 *)&stdindxhead.qwBaseOffset ; *p64 = buff->qwOffset; stdindxhead.nEntriesInUse = num; #if FATFS_OPENDML stdofset = osal_ftell(f); #else stdofset = 0; #endif fillsize =512-((sizeof(AVISTDINDEXHEAD)+ num*sizeof(stdindx))%512); if(type){ // _os_printf("aia"); stdindxhead.fcc = 0x31307869; // "ix01" stdindxhead.dwChunkId = 0x62773130; //"01dw" #if FATFS_OPENDML ret = osal_fwrite((void*)&stdindxhead, 1,sizeof(AVISTDINDEXHEAD),f); ret |= osal_fwrite ((void*)&buff->astdindx,1, sizeof(stdindx)*num,f); /* Write data to a file */ #endif buff->aidxcount = 0; memset((void *)&buff->astdindx,0,sizeof(stdindx)*num); } else{ //_os_printf("via"); stdindxhead.fcc = 0x30307869; // "ix00" stdindxhead.dwChunkId = 0x63643030; //"00cd" #if FATFS_OPENDML ret |= osal_fwrite ((void*)&stdindxhead, 1,sizeof(AVISTDINDEXHEAD) ,f); /* Write data to a file */ ret |= osal_fwrite ((void*)&buff->vstdindx,1,sizeof(stdindx)*num,f); /* Write data to a file */ #endif buff->vidxcount = 0; memset((void *)&buff->vstdindx,0,sizeof(stdindx)*num); } if(fillsize != 512 ){ // _os_printf("fill size:%d",fillsize); //memset((void *)junk,0,512); junk[0] = 0x4b4e554a;//junk junk[1] = fillsize-8; #if FATFS_OPENDML ret |= osal_fwrite ((void*)&junk,1, 8,f);//写入junk头,为什么没有判断是否足够8字节?这里有点小问题,暂时不管 ret |= osal_fseek(f, osal_ftell(f)+fillsize-8); #endif } if(ret == 0)return false; return supindxbuff_updata(type,stdofset,size,num,buff); } /************************************************************** * name :ODMLadd_indx * function :when the video or audio frame wtite to sd card record * their offset and size to the stdindx buff * *************************************************************/ bool ODMLadd_indx(bool type,void *f, ODMLBUFF *buff)//0 is video { //static uint32 count = 0; bool ret = true; //_os_printf("%s:%d\t%X\n",__FUNCTION__,__LINE__,f); if(type) { buff->astdindx[buff->aidxcount].dwOffset = buff->fileofset+8 - buff->qwOffset; buff->astdindx[buff->aidxcount].dwSize = buff->size-8; buff->aidxcount++; if(buff->aidxcount == StdIDXBUFLEN) { #if FATFS_OPENDML ret &= stdidx_write2disk(1,f,buff->aidxcount,buff,osal_fwrite); #else ret &= stdidx_write2disk(1,f,buff->aidxcount,buff,NULL); #endif #if SYNC_EN if(buff->vidxcount != 0){ ret&= stdidx_write2disk(0,f,buff->vidxcount,buff,osal_fwrite); } OdmlSyncAVIInfo(f,buff,buff->vframecnt?1:0); #endif } } else { buff->vstdindx[buff->vidxcount].dwOffset = buff->fileofset+8 - buff->qwOffset; buff->vstdindx[buff->vidxcount].dwSize = buff->size-8; buff->vidxcount++; if(buff->vidxcount == StdIDXBUFLEN) { #if FATFS_OPENDML ret&=stdidx_write2disk(0,f,buff->vidxcount,buff,osal_fwrite); #else ret &= stdidx_write2disk(1,f,buff->aidxcount,buff,NULL); #endif #if SYNC_EN if(buff->aidxcount != 0){ ret&=stdidx_write2disk(1,f,buff->aidxcount,buff,osal_fwrite); } OdmlSyncAVIInfo(f,buff,buff->vframecnt?1:0); #endif } } return ret; } struct avi_test_head { uint32 head; uint32 size; }; // void opendml_write_video(ODMLBUFF *odml_buff,void *fp,void *jpeg,int size) { struct avi_test_head avi_head; struct avi_test_head junk_head; int tell; int flag; static int w_flag = 0; odml_buff->fileofset = osal_ftell(fp); //预先计算是否要写junk tell = osal_ftell(fp); //8是00dc size tell = 0x200 - ((tell+((size+3)&(~0x03))+8)&(0x1ff)); if(tell>8) { flag = 1; //_os_printf("tell:%d\n",tell); avi_head.size = ((size+3)&(~0x03)); avi_head.head = 0x63643030;//00dc junk_head.size = tell-8; junk_head.head = 0x4b4e554a;//junk } else { flag = 0; avi_head.size = ((size+3)&(~0x03)) + tell; avi_head.head = 0x63643030; } osal_fwrite(&avi_head,1,8,fp); //这里替换要实现写图片的操作 osal_fwrite(jpeg,1,size,fp); if(avi_head.size-size) { osal_fseek(fp,osal_ftell(fp)+avi_head.size-size); } odml_buff->size = avi_head.size+8; if(!w_flag) { w_flag = 1; _os_printf("size:%X\n",odml_buff->size ); } //图片4byte对齐 if(odml_buff->size%4) { odml_buff->size += 4-(odml_buff->size%4); osal_fseek(fp,osal_ftell(fp)+(4-(odml_buff->size%4))); } //junk填写,512对齐,不足8byte,则当作是图片数据,大于等于8byte,则填写junk if(flag) { osal_fwrite(&junk_head,1,8,fp); osal_fseek(fp,osal_ftell(fp)+junk_head.size); } odml_buff->inserofset= odml_buff->fileofset; //save jfile ofset for insert jpg odml_buff->insersize= odml_buff->size; odml_buff->vframecnt++; ODMLadd_indx(0,fp,odml_buff); } int opendml_write_video2(ODMLBUFF *odml_buff,void *fp,opendml_write_priv write_priv,int size,void *d) { int res_err = -1; int len; if(!fp) { return res_err; } struct avi_test_head avi_head; struct avi_test_head junk_head; int tell; int flag; odml_buff->fileofset = osal_ftell(fp); //预先计算是否要写junk tell = osal_ftell(fp); //8是00dc size tell = 0x200 - ((tell+((size+3)&(~0x03))+8)&(0x1ff)); if(tell>8 && tell != 0x200) { flag = 1; //_os_printf("tell:%d\n",tell); avi_head.size = ((size+3)&(~0x03)); avi_head.head = 0x63643030;//00dc junk_head.size = tell-8; junk_head.head = 0x4b4e554a;//junk } else { flag = 0; if(tell == 0x200) { tell = 0; } avi_head.size = ((size+3)&(~0x03)) + tell; avi_head.head = 0x63643030; } len = osal_fwrite(&avi_head,1,8,fp); if(len == 0) { goto opendml_write_video2_end; } //这里替换要实现写图片的操作 //osal_fwrite(jpeg,1,size,fp); len = write_priv(fp,d,size); if(len < 0) { goto opendml_write_video2_end; } if(avi_head.size-size) { osal_fseek(fp,osal_ftell(fp)+avi_head.size-size); } odml_buff->size = avi_head.size+8; //图片4byte对齐 if(odml_buff->size%4) { odml_buff->size += 4-(odml_buff->size%4); osal_fseek(fp,osal_ftell(fp)+(4-(odml_buff->size%4))); } //junk填写,512对齐,不足8byte,则当作是图片数据,大于等于8byte,则填写junk if(flag) { len = osal_fwrite(&junk_head,1,8,fp); if(len == 0) { goto opendml_write_video2_end; } osal_fseek(fp,osal_ftell(fp)+junk_head.size); } odml_buff->inserofset= odml_buff->fileofset; //save jfile ofset for insert jpg odml_buff->insersize= odml_buff->size; odml_buff->vframecnt++; ODMLadd_indx(0,fp,odml_buff); res_err = 0; opendml_write_video2_end: return res_err; } int opendml_write_audio(ODMLBUFF *odml_buff,void *fp,opendml_write_priv write_priv,int size,void *d) { int res_err = -1; int len; if(!fp) { return -1; } struct avi_test_head avi_head; struct avi_test_head junk_head; int tell; int flag; odml_buff->fileofset = osal_ftell(fp); //预先计算是否要写junk tell = osal_ftell(fp); //8是00dc size tell = 0x200 - ((tell+((size+3)&(~0x03))+8)&(0x1ff)); if(tell>8 && tell != 0x200) { flag = 1; //_os_printf("tell:%d\n",tell); avi_head.size = ((size+3)&(~0x03)); avi_head.head = 0x62773130;//01wb junk_head.size = tell-8; junk_head.head = 0x4b4e554a;//junk } else { flag = 0; if(tell == 0x200) { tell = 0; } avi_head.size = ((size+3)&(~0x03)); avi_head.head = 0x62773130; } len = osal_fwrite(&avi_head,1,8,fp); if(len == 0) { goto opendml_write_audio_end; } //这里替换要实现写图片的操作 //osal_fwrite(jpeg,1,size,fp); len = write_priv(fp,d,size); if(len < 0) { goto opendml_write_audio_end; } if(avi_head.size-size) { osal_fseek(fp,osal_ftell(fp)+avi_head.size-size); } odml_buff->size = avi_head.size+8; //图片4byte对齐 if(odml_buff->size%4) { odml_buff->size += 4-(odml_buff->size%4); osal_fseek(fp,osal_ftell(fp)+(4-(odml_buff->size%4))); } //junk填写,512对齐,不足8byte,则当作是图片数据,大于等于8byte,则填写junk if(flag) { len = osal_fwrite(&junk_head,1,8,fp); if(len == 0) { goto opendml_write_audio_end; } osal_fseek(fp,osal_ftell(fp)+junk_head.size); } odml_buff->inserofset= odml_buff->fileofset; //save jfile ofset for insert jpg odml_buff->insersize= odml_buff->size; odml_buff->aframecnt++; ODMLadd_indx(1,fp,odml_buff); res_err = 0; opendml_write_audio_end: return res_err; } int insert_frame(ODMLBUFF *buff,void *pavi,float *tim_diff) { /*??????*/ // static int time_diff = 0; int i; float everyframe_time = 1000.0/buff->ef_fps; int insert_num = 1; if(buff->cur_timestamp==0 || 0 == buff->last_timestamp) return 0; //增加时间差,后面还需要减去一帧的时间差 *tim_diff += buff->cur_timestamp - buff->last_timestamp ;//- buff->ef_time; // os_printf("buf_cur_timestamp:%d,last_timestamp:%d tim_diff+=%d\n",buff->cur_timestamp, // buff->last_timestamp, // buff->cur_timestamp - buff->last_timestamp); //减去一帧,已经保存的一帧 *tim_diff -=everyframe_time; // _os_printf("tim_diff:%d\n",*tim_diff); if(*tim_diff > everyframe_time) { #if 0 //通过音频校准视频,方法是插帧,但音频帧-1是由于可能存在有些视频帧存在缓存中,因此-1 if(buff->aframecnt!=0 && (buff->aframecnt-1)*(PCM_SHEET_SIZE-8)*3>buff->vframecnt*100*32+(*tim_diff)*96) { *tim_diff = (buff->aframecnt-1)*(PCM_SHEET_SIZE-8)/32-buff->vframecnt*100/3;//音频比视频多的时间就是需要补帧的数量,原公式为(buff->aframecnt-1)*(PCM_SHEET_SIZE-8)/32000*1000-buff.vframecnt/30*1000; } #endif #if 1 //计算一次补多少帧,100ms大约3帧,则一次补1帧 if(*tim_diff<150) { insert_num = 1; } //250ms大约9帧,则一次补2帧 else if(*tim_diff<250) { insert_num = 2; } //500ms大约16-17帧,则一次补2帧 else if(*tim_diff<500) { insert_num = 3; } //其他的话,就补4帧 else { insert_num = 4; //insert_num = (*tim_diff)/(1000/(buff->ef_fps)); } #else insert_num = (*tim_diff)/everyframe_time; // printf("============tim_diff:%f every_frame_time:%f insert_num:%d (*tim_diff)/everyframe_time:%f\n", // *tim_diff,everyframe_time, // insert_num, // (*tim_diff)/everyframe_time); #endif buff->vframecnt+=insert_num; //os_printf("tim_diff:%f\n",*tim_diff); *tim_diff -= ((insert_num)*everyframe_time); //os_printf("*tim_diff -= ((insert_num)*everyframe_time):%f, ((insert_num)*everyframe_time:%f\n",*tim_diff,((insert_num)*everyframe_time)); for(i=0;i