Files
fmviewer3/project/fm_viewer/data/rm_format_avi.cpp
2026-02-21 17:11:31 +09:00

884 lines
26 KiB
C++

#if (FILE_FORMAT_AVI)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if !defined(BBEXTRACT)
#include <QtCore>
#include "rm_constants.h"
#if (APPLICATION_PROFILE)
#include <QElapsedTimer>
#include <QDebug>
#endif
#endif //#if !defined(BBEXTRACT)
#include "rm_format_avi.h"
extern "C" {
#include "fileio.h"
}
// 참조: https://github.com/masayukig/jpegtoavi/blob/master/aviformat.txt
// http://telnet.or.kr/directx/htm/avirifffilereference.htm
// http://blog.naver.com/PostView.nhn?blogId=shlee7708&logNo=120121689464 <- 제일 편함!!
//static int skip_chunk(FILE *in)
//{
//char chunk_id[5];
//int chunk_size;
//int end_of_chunk;
// read_chars(_file,chunk_id,4);
// chunk_size=read_long(_file);
// printf("Uknown Chunk at %d\n",(int)ftell(_file));
// printf("-------------------------------\n");q
// printf(" chunk_id: %s\n",chunk_id);
// printf(" chunk_size: %d\n",chunk_size);
// printf("\n");
// end_of_chunk=ftell(_file)+chunk_size;
// if ((end_of_chunk%4)!=0)
// {
// end_of_chunk=end_of_chunk+(4-(end_of_chunk%4));
// }
// RMfseek(_file,end_of_chunk,SEEK_SET);
// return 0;
//}
//AVIRiff(RMfile in,bool durationOnly = false);
AVIRiff::AVIRiff(RMfile in,VideoReadMode mode, VideoPreInfo* info)
{
_readMode = mode;
_preInfo = info;
#if (SENSOR_AVI_SUBTITLE)
subtitles = NULL;
#endif
if(_preInfo != NULL) {
_preInfo->bDuration = false;
_preInfo->duration = 0;
#if (CHECK_VIDEO_BITRATE)
_preInfo->movSize = 0;
_preInfo->bMOVSize = false;
#endif
_preInfo->width = 0;
_preInfo->height = 0;
}
_isValid = false;
_file = in;
_videoStreamCount = 0;
#if (AVI_CHUNHO_SENSOR_FORMAT_1)
_gps_buffer = NULL;
_sensor_buffer = NULL;
_gps_buffer_size = 0;
_sensor_buffer_size = 0;
#endif
parse_riff();
}
AVIRiff::~AVIRiff()
{
for(int i=0;i<_videoStreamCount;i++)
{
if(_videoStreamFormat[i].palette != NULL)
{
free(_videoStreamFormat[i].palette);
}
}
#if (AVI_CHUNHO_SENSOR_FORMAT_1)
if(_gps_buffer != NULL)
{
free(_gps_buffer);
}
if(_sensor_buffer != NULL)
{
free(_sensor_buffer);
}
#endif
#if (SENSOR_AVI_SUBTITLE)
if(subtitles != NULL) {
for(int i=0;i<subtitles->size();i++) {
free(subtitles->at(i));
}
delete subtitles;
subtitles = NULL;
}
#endif
}
int AVIRiff::hex_dump_chunk(int chunk_len)
{
#if (USE_AVI_DUMP)
char chars[17];
int ch,n;
chars[16]=0;
int line = 0;
for (n=0; n<chunk_len; n++)
{
if ((n%16)==0)
{
if (n!=0)
{
printf("%s\n", chars);
}
printf("%04d ",line++);
memset(chars, ' ', 16);
}
ch=getc(_file);
if (ch==EOF)
{
break;
}
printf("%02x ", ch);
if (ch>=' ' && ch<=126)
{
chars[n%16]=ch;
}
else
{
chars[n%16]='.';
}
}
if ((n%16)!=0)
{
for (ch=n%16; ch<16; ch++)
{
printf(" ");
}
}
printf("%s\n", chars);
#else
#if !defined(BBEXTRACT)
Q_UNUSED(chunk_len);
#endif // #if !defined(BBEXTRACT)
#endif
return 0;
}
#if (DEBUG_AVI_FORMAT)
int AVIRiff::parse_idx1(int chunk_len)
{
index_entry_t index_entry;
int t;
printf(" IDX1\n");
printf(" -------------------------------\n");
printf(" ckid dwFlags dwChunkOffset dwChunkLength\n");
for (t=0; t<chunk_len/16; t++)
{
read_chars(_file,index_entry.ckid,4);
index_entry.dwFlags=read_long(_file);
index_entry.dwChunkOffset=read_long(_file);
index_entry.dwChunkLength=read_long(_file);
printf(" %s 0x%08x 0x%08x 0x%08x\n",
index_entry.ckid,
index_entry.dwFlags,
index_entry.dwChunkOffset,
index_entry.dwChunkLength);
}
printf("\n");
return 0;
}
#endif
int AVIRiff::read_avi_header() // ,struct avi_header_t *avi_header
{
// 연결되지 않은 영상 Bit rate : 121 kb/s
// 연결된 영상 Bit rate : 4 493 kb/s
//long offset=ftell(_file);
AVIHeader* avi_header = &_avi_header;
avi_header->TimeBetweenFrames=read_long(_file); // AVI TYPE 1 = 0
avi_header->MaximumDataRate=read_long(_file);
avi_header->PaddingGranularity=read_long(_file);
avi_header->Flags=read_long(_file);
avi_header->TotalNumberOfFrames=read_long(_file);
avi_header->NumberOfInitialFrames=read_long(_file);
avi_header->NumberOfStreams=read_long(_file);
avi_header->SuggestedBufferSize=read_long(_file);
avi_header->Width=read_long(_file);
avi_header->Height=read_long(_file);
avi_header->TimeScale=read_long(_file);
avi_header->DataRate=read_long(_file);
avi_header->StartTime=read_long(_file);
avi_header->DataLength=read_long(_file);
if(_preInfo != NULL)
{
_preInfo->width = avi_header->Width;
_preInfo->height = avi_header->Height;
}
#if (DEBUG_AVI_HEADER)
printf(" offset=0x%lx\n",offset);
printf(" TimeBetweenFrames: %d\n",avi_header->TimeBetweenFrames);
printf(" MaximumDataRate: %d\n",avi_header->MaximumDataRate);
printf(" PaddingGranularity: %d\n",avi_header->PaddingGranularity);
printf(" Flags: %d\n",avi_header->Flags);
printf(" TotalNumberOfFrames: %d\n",avi_header->TotalNumberOfFrames);
printf(" NumberOfInitialFrames: %d\n",avi_header->NumberOfInitialFrames);
printf(" NumberOfStreams: %d\n",avi_header->NumberOfStreams);
printf(" SuggestedBufferSize: %d\n",avi_header->SuggestedBufferSize);
printf(" Width: %d\n",avi_header->Width);
printf(" Height: %d\n",avi_header->Height);
printf(" TimeScale: %d\n",avi_header->TimeScale);
printf(" DataRate: %d\n",avi_header->DataRate);
printf(" StartTime: %d\n",avi_header->StartTime);
printf(" DataLength: %d\n",avi_header->DataLength);
fflush(stdout);
#endif
return 0;
}
void AVIRiff::print_data_handler(unsigned char *handler)
{
int t;
for (t=0; t<4; t++)
{
if ((handler[t]>='a' && handler[t]<='z') ||
(handler[t]>='A' && handler[t]<='Z') ||
(handler[t]>='0' && handler[t]<='9'))
{
printf("%c",handler[t]);
}
else
{
printf("[0x%02x]",handler[t]);
}
}
}
int AVIRiff::read_stream_header(stream_header_t *stream_header)
{
#if (DEBUG_AVI_STREAM_HEADER)
long offset=ftell(_file);
#endif
read_chars(_file,stream_header->DataType,4);
read_chars(_file,stream_header->DataHandler,4);
stream_header->Flags=read_long(_file);
stream_header->Priority=read_long(_file);
stream_header->InitialFrames=read_long(_file);
stream_header->TimeScale=read_long(_file);
stream_header->DataRate=read_long(_file);
stream_header->StartTime=read_long(_file);
stream_header->DataLength=read_long(_file);
stream_header->SuggestedBufferSize=read_long(_file);
stream_header->Quality=read_long(_file);
stream_header->SampleSize=read_long(_file);
if(_preInfo != NULL) {
if(_preInfo->duration == 0 && stream_header->TimeScale != 0)
{
_preInfo->bDuration = true;
_preInfo->duration = (unsigned int)(((double)(stream_header->TimeScale * 1000) / (double)stream_header->DataRate) * (double)stream_header->DataLength);
}
}
#if (DEBUG_AVI_STREAM_HEADER)
printf("------------------------------------------------------------\n");
printf(" offset=0x%lx\n",offset);
printf(" DataType: %s\n",stream_header->DataType);
printf(" DataHandler: ");
print_data_handler((unsigned char *)stream_header->DataHandler);
printf("\n");
printf(" Flags: %d\n",stream_header->Flags);
printf(" Priority: %d\n",stream_header->Priority);
printf(" InitialFrames: %d\n",stream_header->InitialFrames);
printf(" TimeScale: %d\n",stream_header->TimeScale);
printf(" DataRate: %d\n",stream_header->DataRate);
printf(" StartTime: %d\n",stream_header->StartTime);
printf(" DataLength: %d\n",stream_header->DataLength);
printf(" SuggestedBufferSize: %d\n",stream_header->SuggestedBufferSize);
printf(" Quality: %d\n",stream_header->Quality);
printf(" SampleSize: %d\n",stream_header->SampleSize);
fflush(stdout);
#endif
return 0;
}
int AVIRiff::read_stream_format(stream_format_t *stream_format)
{
int t,r,g,b;
#if (DEBUG_AVI_FORMAT)
long offset=ftell(_file);
#endif
stream_format->header_size=read_long(_file);
stream_format->image_width=read_long(_file);
stream_format->image_height=read_long(_file);
stream_format->number_of_planes=read_word(_file);
stream_format->bits_per_pixel=read_word(_file);
stream_format->compression_type=read_long(_file);
stream_format->image_size_in_bytes=read_long(_file);
stream_format->x_pels_per_meter=read_long(_file);
stream_format->y_pels_per_meter=read_long(_file);
stream_format->colors_used=read_long(_file);
stream_format->colors_important=read_long(_file);
stream_format->palette=0;
if (stream_format->colors_important!=0)
{
stream_format->palette= (int*) malloc(stream_format->colors_important*sizeof(int));
for (t=0; t<stream_format->colors_important; t++)
{
b=RMgetc(_file);
g=RMgetc(_file);
r=RMgetc(_file);
stream_format->palette[t]=(r<<16)+(g<<8)+b;
}
}
#if (DEBUG_AVI_FORMAT)
printf(" offset=0x%lx\n",offset);
printf(" header_size: %d\n",stream_format->header_size);
printf(" image_width: %d\n",stream_format->image_width);
printf(" image_height: %d\n",stream_format->image_height);
printf(" number_of_planes: %d\n",stream_format->number_of_planes);
printf(" bits_per_pixel: %d\n",stream_format->bits_per_pixel);
printf(" compression_type: %04x (%c%c%c%c)\n",stream_format->compression_type,
((stream_format->compression_type)&255),
((stream_format->compression_type>>8)&255),
((stream_format->compression_type>>16)&255),
((stream_format->compression_type>>24)&255));
printf(" image_size_in_bytes: %d\n",stream_format->image_size_in_bytes);
printf(" x_pels_per_meter: %d\n",stream_format->x_pels_per_meter);
printf(" y_pels_per_meter: %d\n",stream_format->y_pels_per_meter);
printf(" colors_used: %d\n",stream_format->colors_used);
printf(" colors_important: %d\n",stream_format->colors_important);
fflush(stdout);
#endif
return 0;
}
int AVIRiff::read_stream_format_auds(stream_format_auds_t *stream_format)
{
#if (DEBUG_AVI_FORMAT)
long offset=RMftell(_file);
#endif
stream_format->format=read_word(_file);
stream_format->channels=read_word(_file);
stream_format->samples_per_second=read_long(_file);
stream_format->bytes_per_second=read_long(_file);
#if (DEBUG_AVI_FORMAT)
int block_align=read_word(_file);
#endif
stream_format->block_size_of_data=read_word(_file);
stream_format->bits_per_sample=read_word(_file);
//stream_format->extended_size=read_word(_file);
#if (DEBUG_AVI_FORMAT)
printf(" offset=0x%lx\n",offset);
printf(" format: %d\n",stream_format->format);
printf(" channels: %d\n",stream_format->channels);
printf(" samples_per_second: %d\n",stream_format->samples_per_second);
printf(" bytes_per_second: %d\n",stream_format->bytes_per_second);
printf(" block_align: %d\n",block_align);
printf(" block_size_of_data: %d\n",stream_format->block_size_of_data);
printf(" bits_per_sample: %d\n",stream_format->bits_per_sample);
#endif
return 0;
}
int AVIRiff::parse_hdrl_list()
{
// stream_format_auds_t stream_format_auds;
// stream_header_t stream_header_auds;
char chunk_id[5];
int chunk_size;
char chunk_type[5];
int end_of_chunk;
int next_chunk;
//long offset=RMftell(_file);
AVI_STREAM_TYPE stream_type = UNDEFINED_STREAM;
read_chars(_file,chunk_id,4);
chunk_size=read_long(_file);
read_chars(_file,chunk_type,4);
#if (DEBUG_AVI_FORMAT)
printf(" AVI Header LIST (id=%s size=%d type=%s offset=0x%lx)\n",chunk_id,chunk_size,chunk_type,offset);
printf(" {\n");
#endif
end_of_chunk=RMftell(_file)+chunk_size-4;
if ((end_of_chunk%4)!=0)
{
//printf("Adjusting end of chunk %d\n", end_of_chunk);
//end_of_chunk=end_of_chunk+(4-(end_of_chunk%4));
//printf("Adjusting end of chunk %d\n", end_of_chunk);
}
if (strcmp(chunk_id,"JUNK")==0)
{
RMfseek(_file,end_of_chunk,SEEK_SET);
#if (DEBUG_AVI_FORMAT)
printf(" }\n");
#endif
return 0;
}
while (RMftell(_file)<end_of_chunk)
{
//long offset=RMftell(_file);
read_chars(_file,chunk_type,4);
chunk_size=read_long(_file);
next_chunk=RMftell(_file)+chunk_size;
if ((chunk_size%4)!=0)
{
//printf("Chunk size not a multiple of 4?\n");
//chunk_size=chunk_size+(4-(chunk_size%4));
}
#if (DEBUG_AVI_FORMAT)
printf(" %.4s (size=%d offset=0x%lx)\n",chunk_type,chunk_size,offset);
printf(" {\n");
#endif
if (strcasecmp("strh",chunk_type)==0)
{
long marker=RMftell(_file);
char buffer[5];
read_chars(_file,buffer,4);
RMfseek(_file,marker,SEEK_SET);
if (strcmp(buffer, "vids")==0)
{
stream_type = VIDEO_STREAM;
read_stream_header(&_videoStreamHeaders[_videoStreamCount]); // format 읽은후에 ++
}
else if (strcmp(buffer, "auds")==0)
{
stream_type = AUDIO_STREAM;
read_stream_header(&_audioStreamHeader);
}
else if (strcmp(buffer, "txts")==0)
{
stream_type = TXT_STREAM;
read_stream_header(&_txtStreamHeader);
}
else
{
#if (DEBUG_AVI_FORMAT)
printf("Unknown stream type %s\n", buffer);
#endif
return -1;
}
}
else if (strcasecmp("strf",chunk_type)==0)
{
if (stream_type == VIDEO_STREAM)
{
read_stream_format(&_videoStreamFormat[_videoStreamCount]);
_videoStreamCount++;
}
else if (stream_type==1)
{
read_stream_format_auds(&_audioStreamFormat);
}
else if (stream_type==2) // subtitle
{
// STRF 에는 아무 정보도 없음
//hex_dump_chunk(in,371);
//read_stream_format_auds(in,&stream_format_auds);
}
}
else if (strcasecmp("strd",chunk_type)==0)
{
//RMfseek(_file,offset,SEEK_SET);
//read_strd_format(chunk_size);
//_stopProcessing = true;
}
else
{
#if (DEBUG_AVI_FORMAT)
printf(" Unknown chunk type: %s\n",chunk_type);
#endif
// skip_chunk(_file);
}
#if (DEBUG_AVI_FORMAT)
printf(" }\n");
#endif
RMfseek(_file,next_chunk,SEEK_SET);
}
//printf("@@@@ %ld %d\n", RMftell(_file), end_of_chunk);
#if (DEBUG_AVI_FORMAT)
printf(" }\n");
#endif
RMfseek(_file,end_of_chunk,SEEK_SET);
return 0;
}
#if (SENSOR_AVI_SUBTITLE)
// 자막 데이터 AVI TYPE2
int AVIRiff::add_subtitle(long chunkSize)
{
if(subtitles == NULL) {
subtitles = new QList<char*>();
}
char* buffer = (char*)malloc(chunkSize + 1);
memset(buffer,0,chunkSize + 1);
RMfread(buffer,chunkSize,1,_file);
//qInfo() << buffer;
//QString str = QString(buffer);
subtitles->append(buffer);
//free(buffer);
return 0;
}
#endif
int AVIRiff::parse_movi_list(unsigned int size)
{
#if (APPLICATION_PROFILE)
QElapsedTimer timer;
timer.start();
#endif
char chunk_id[5] = {0,};
long chunk_size;
long end_of_chunk;
long offset=RMftell(_file);
#if (DEBUG_AVI_MOVI)
printf(" AVI MOVI Chunk (id=%s size=%d offset=0x%lx)\n",chunk_id,chunk_size,offset);
printf(" {\n");
fflush(stdout);
#endif
//int txtCount = 0;
while(RMftell(_file)< offset+(long)size-4)
{
read_chars(_file,chunk_id,4); // 4 byte
chunk_size=read_long(_file); // 4 byte
// pack 하지 않는다.. 다음 chunk 의 chunk_id + size 제외하고 이동
end_of_chunk= RMftell(_file) + chunk_size;
// H265 AVI 는 2 BYTE pack 되어 있음..
if ((end_of_chunk % 2) == 1)
{
end_of_chunk += 1;
}
if(chunk_id[2] == 't' && chunk_id[3] == 'x')
{
#if (SENSOR_AVI_SUBTITLE)
add_subtitle(chunk_size);
#endif
#if (DEBUG_AVI_MOVI)
printf(" MOVI TXT (id(%04d)=%s size=%d offset=%ld)\n",txtCount++,chunk_id,chunk_size,ftell(_file));
// hex_dump_chunk(chunk_size);
fflush(stdout);
#endif
}
else
{
// 이후 NAL SEI 처리 기능 추가
}
RMfseek(_file,end_of_chunk,SEEK_SET);
}
#if (DEBUG_AVI_MOVI)
printf(" }\n");
fflush(stdout);
#endif
#if (APPLICATION_PROFILE)
qInfo () << "Elapsed Time(parse_movi_list):" << timer.elapsed() << " msec" << " count:" << txtCount;
#endif
return 0;
}
//int AVIRiff::parse_hdrl(stream_format_t *stream_format, unsigned int size)
int AVIRiff::parse_hdrl(unsigned int size)
{
char chunk_id[5];
long chunk_size;
long end_of_chunk;
long offset=RMftell(_file);
read_chars(_file,chunk_id,4);
chunk_size=read_long(_file);
#if (DEBUG_AVI_FORMAT)
printf(" AVI Header Chunk (id=%s size=%d offset=0x%lx)\n",chunk_id,chunk_size,offset);
printf(" {\n");
#endif
end_of_chunk=RMftell(_file)+chunk_size;
if ((end_of_chunk%4)!=0) // 4BYTE PACK
{
end_of_chunk=end_of_chunk+(4-(end_of_chunk%4));
}
read_avi_header(); // 메인 헤더 읽기
#if (DEBUG_AVI_FORMAT)
printf(" }\n");
#endif
while(RMftell(_file)<offset+(long)size-4)
{
//printf("Should end at 0x%lx 0x%lx\n",offset+size,RMftell(_file));
parse_hdrl_list();
//parse_hdrl_list(stream_header,stream_format);
}
return 0;
}
int AVIRiff::parse_riff()
{
_isValid = false; // TAG 문제시만..
// 개별 chunk 처리
char chunk_id[5] = {0,};
int chunk_size;
char chunk_type[5] = {0,};
int end_of_chunk, end_of_subchunk;
//struct avi_header_t avi_header;
// stream_header_t stream_header;
// stream_format_t stream_format={0};
read_chars(_file,chunk_id,4);
chunk_size=read_long(_file);
read_chars(_file,chunk_type,4);
#if (DEBUG_AVI_FORMAT)
long offset=RMftell(_file);
printf("RIFF Chunk (id=%s size=%d type=%s offset=0x%lx)\n",chunk_id,chunk_size,chunk_type, offset);
printf("{\n");
#endif
if (strcasecmp("RIFF",chunk_id)!=0)
{
//printf("Not a RIFF file.\n");
return 1;
}
else if (strcasecmp("AVI ",chunk_type)!=0)
{
//printf("Not an AVI file.\n");
return 1;
}
end_of_chunk=RMftell(_file)+chunk_size-4;
#if (AVI_CHUNHO_SENSOR_FORMAT_1)
// Sensor 는 STRD 와 유사하게 end_of_chunk 뒤에 위치함
if(_preInfo == NULL)
{
RMfseek(_file,end_of_chunk,SEEK_SET);
bool b_gps_read = false;
bool b_sensor_read = false;
// 파일 끝까지 확인
int tryCount = 0;
while (RMfeof(_file) == 0 && tryCount++ < 100)
{
int offset = RMftell(_file);
#if !defined(BBEXTRACT)
QString offsetStr;
offsetStr.sprintf("%08X",offset);
#endif
read_chars(_file,chunk_id,4); // ID
chunk_size=read_long(_file); // 크기
// 센서 데이터 깨진 파일이 존재함 (chunck offset 이 짧거나..)
// qInfo() << "chunk_id:" << chunk_id << " chunk_size:" << chunk_size << " offset:" << offsetStr;
//end_of_subchunk=RMftell(_file)+chunk_size; // 범위 지정
//IDIT : 9355386 = 20
//gpsa : 9355398 = 4
//gps0 : 9357326 = 1920
//gsea : 9357354 = 20
//gsen : 9361576 = 4214
// 14 BYTE
if (strcasecmp("gps0",chunk_id)==0)
{
_gps_buffer_size = chunk_size;
_gps_buffer = (uint8_t*)malloc(chunk_size);
RMfread(_gps_buffer,_gps_buffer_size,1,_file);
b_gps_read = true;
}
else if (strcasecmp("gsen",chunk_id)==0)
{
if(chunk_size > 0) {
//qInfo() << "gsen offset:" << offsetStr;
_sensor_buffer_size = chunk_size;
_sensor_buffer = (uint8_t*)malloc(chunk_size);
RMfread(_sensor_buffer,_sensor_buffer_size,1,_file);
b_sensor_read = true;
}
}
// 깨진 데이터는 1 BYTE 씩 탐색
else if(chunk_size < 0 ||
(strcasecmp("IDIT",chunk_id) != 0 &&
strcasecmp("gpsa",chunk_id) != 0 &&
strcasecmp("gsea",chunk_id) != 0)) {
chunk_size = -7;
}
end_of_subchunk = offset + 8 + chunk_size;
if(b_sensor_read && b_gps_read)
{
break;
}
//qInfo() << chunk_id << ":" << end_of_subchunk << " =" << chunk_size;
RMfseek(_file,end_of_subchunk,SEEK_SET);
}
_isValid = true;
return 0;
}
#endif
while (RMftell(_file)<end_of_chunk)
{
read_chars(_file,chunk_id,4); // ID
chunk_size=read_long(_file); // 크기
end_of_subchunk=RMftell(_file)+chunk_size; // 범위 지정
if (strcasecmp("JUNK",chunk_id)==0 || strcasecmp("PAD ",chunk_id)==0) // ID 가 JUNK 또는 PAD 일 경우 ...
{
chunk_type[0]=0;
}
else
{
read_chars(_file,chunk_type,4); // 타입이 존재할 경우
}
#if (DEBUG_AVI_FORMAT)
long offset=RMftell(_file); // 현재 옵셋
printf(" New Chunk (id=%s size=%d type=%s offset=0x%lx)\n",chunk_id,chunk_size,chunk_type,offset);
printf(" {\n");
fflush(stdout);
#endif
if (strcasecmp("JUNK",chunk_id)==0 || strcasecmp("PAD ",chunk_id)==0) // 사용되지 않음
{
if ((chunk_size%4)!=0)
{
chunk_size=chunk_size+(4-(chunk_size%4));
}
#if (DEBUG_AVI_JUNK)
hex_dump_chunk(chunk_size);
#endif
}
else if (strcasecmp("INFO",chunk_type)==0) // 사용되지 않음..
{
if ((chunk_size%4)!=0)
{
chunk_size=chunk_size+(4-(chunk_size%4));
}
#if (DEBUG_AVI_INFO)
hex_dump_chunk(chunk_size);
#endif
}
else if (strcasecmp("hdrl",chunk_type)==0) // 헤더 리스트 처리
{
parse_hdrl(chunk_size);
// 기본 모드가 아닐 경우 종료 (subtitle 모델 체크는 subtitle 확인해야함)
// skip_chunk(_file);
}
else if (strcasecmp("movi",chunk_type)==0) // 'movi' 리스트 처리
{
#if (CHECK_VIDEO_BITRATE)
if(_readMode == AVIReadMOVSize && _preInfo != NULL) {
_preInfo->bMOVSize = true;
_preInfo->movSize = chunk_size;
}
#endif
// 처리할 필요 없음
#if (SENSOR_AVI_SUBTITLE)
if(_readMode == VideoReadSensor) {
parse_movi_list(chunk_size);
}
#endif
}
else if (strcasecmp("idx1",chunk_id)==0) // 인덱스 처리
{
RMfseek(_file,RMftell(_file)-4,SEEK_SET);
#if (DEBUG_AVI_FORMAT)
parse_idx1(chunk_size);
#endif
}
else
{
#if (DEBUG_AVI_FORMAT)
printf(" Unknown chunk at %d (%4s)\n",(int)RMftell(_file)-8,chunk_type);
#endif
if (chunk_size==0)
{
break;
}
}
// 필요한 정보 모두 수집되었는지 확인
if(_readMode == VideoReadDuration && _preInfo != NULL && _preInfo->bDuration == true) {
_isValid = true;
return 0;
}
#if (CHECK_VIDEO_BITRATE)
else if(_readMode == VideoReadMOVSize && _preInfo != NULL && _preInfo->bDuration == true && _preInfo->bMOVSize)
{
_isValid = true;
return 0;
}
#endif
RMfseek(_file,end_of_subchunk,SEEK_SET);
#if (DEBUG_AVI_FORMAT)
printf(" }\n");
#endif
}
#if (DEBUG_AVI_FORMAT)
printf("}\n");
#endif
_isValid = true;
return 0;
}
bool AVIRiff::duration(RMfile in, VideoPreInfo* info)
{
AVIRiff avi = AVIRiff(in,VideoReadDuration,info);
return avi.isValid();
}
#if (CHECK_VIDEO_BITRATE)
bool AVIRiff::movSize(RMfile in, VideoPreInfo* info)
{
AVIRiff avi = AVIRiff(in,VideoReadMOVSize,info);
return avi.isValid();
}
#endif
#endif // #if (FILE_FORMAT_AVI)