first commit
This commit is contained in:
883
project/fm_viewer/data/rm_format_avi.cpp
Normal file
883
project/fm_viewer/data/rm_format_avi.cpp
Normal file
@@ -0,0 +1,883 @@
|
||||
#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)
|
||||
Reference in New Issue
Block a user