#ifndef RM_FORMAT_AVI_H #define RM_FORMAT_AVI_H #if (FILE_FORMAT_AVI) #if !defined(BBEXTRACT) #include "../rm_include.h" #include #endif #include "rm_format.h" #pragma once #include #include #include #ifdef _MSC_VER #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif extern "C" { #include "fileio.h" } // DEBUG 용 #define DEBUG_AVI_FORMAT 0 #define USE_AVI_DUMP 0 #define DEBUG_AVI_JUNK 0 #define DEBUG_AVI_INFO 0 #define DEBUG_AVI_HEADER 0 // 메인헤더 #define DEBUG_AVI_STREAM_HEADER 0 // 스트림 헤더 #define DEBUG_AVI_MOVI 0 // 스트림 데이터 리스트 // http://www.econote.co.kr/main/view_post.asp?post_seq_no=49407 정리 잘 되어 있음 // AVI RIFF 구조는 // RIFF // - hdrl(LIST) // - avih : AVI 파일 전체 기본 정보 // - strl (LIST) // - strh (vids) : 영상 스트림 헤더 // - strf " 포멧 // - strl (LIST) // - strh (auds) : 음성 스트림 헤더 // - strf " 포멧 // - strl (LIST) // - strh (txts) : 자막 스트림 헤더 // - strf " 포멧 // - IDIT // - INFO(LIST) : 정보 // -ISFT : 업체정보 // - movi(LIST) : 실제 데이터 // - 00dc/b : 음성패킷 (c:압축,b:비압축) // - 00wb/c : 영상패킷 (") // - 00tx : 자막 // - idx1: 프레임의 위치 (binary 로 01wb,flag,offset,size ..... 00dc,flat,offset,size.. #define MAX_VIDEO_STREAM_COUNT 4 // TimeScale 등이 0 라 재생시간 처리에 문제가 생김 // avi 정보 (AVI Header,'avih') typedef struct _AVIHeader { int TimeBetweenFrames; int MaximumDataRate; int PaddingGranularity; int Flags; int TotalNumberOfFrames; int NumberOfInitialFrames; int NumberOfStreams; int SuggestedBufferSize; int Width; int Height; int TimeScale; int DataRate; int StartTime; int DataLength; } AVIHeader; // str(eam) 정보 (Stream Header,'strh') / Video('vids') typedef struct _STRHeader { char DataType[5]; char DataHandler[5]; int Flags; int Priority; int InitialFrames; int TimeScale; int DataRate; int StartTime; int DataLength; int SuggestedBufferSize; int Quality; int SampleSize; } stream_header_t; // str(eam) 포멧 (Stream Format,'strf') / Video('vids') typedef struct _STRFormat { int header_size; int image_width; int image_height; int number_of_planes; int bits_per_pixel; int compression_type; int image_size_in_bytes; int x_pels_per_meter; int y_pels_per_meter; int colors_used; int colors_important; int *palette; } stream_format_t; // str(eam) 정보 (Stream Header,'strh') / Audio('auds') typedef struct _STRHeaderAudio { int format_type; int number_of_channels; int sample_rate; int bytes_per_second; int block_size_of_data; int bits_per_sample; int byte_count_extended; }stream_header_auds_t; // str(eam) 포멧 (Stream Format,'strf') / Video('auds') typedef struct _STRFormatAudio { int header_size; int format; int channels; int samples_per_second; int bytes_per_second; int block_size_of_data; int bits_per_sample; int extended_size; } stream_format_auds_t; // 인덱스 구조 ('idx1') typedef struct _AVIDX { char ckid[5]; int dwFlags; int dwChunkOffset; int dwChunkLength; } index_entry_t; class AVIRiff { private: VideoReadMode _readMode; // 현재 모드 VideoPreInfo* _preInfo; // 기본 정보 (존재할 경우 ReadMode == PreInfo) bool _isValid; // 센서 관련? public: #if (SENSOR_AVI_SUBTITLE) QList* subtitles; // 자막 센서 포멧 #endif AVIRiff(RMfile in,VideoReadMode mode = VideoReadSensor, VideoPreInfo* info = NULL); static bool duration(RMfile in,VideoPreInfo* info); #if (CHECK_VIDEO_BITRATE) static bool movSize(RMfile in,VideoPreInfo* info); #endif ~AVIRiff(); bool isValid() { return _isValid; } // MOV 크기와 재생시간 그리고 오디오 bitrate (kb/sec) 를 입력받아 mov bitrate 를 계산한다 #if (CHECK_VIDEO_BITRATE) static int videoBitrate(VideoPreInfo* info, double audioBitrate = 256) { const double kb = 1000.0; // 1024? const double durationInSec = (double)(info->duration) / 1000.0; double audioSize = durationInSec * audioBitrate * kb / 8.0; // kb SEC double videoSize = (double)(info->movSize) - audioSize; return videoSize * 8.0 / durationInSec / kb; } #endif #if (AVI_CHUNHO_SENSOR_FORMAT_1) uint8_t* _gps_buffer; size_t _gps_buffer_size; uint8_t* _sensor_buffer; size_t _sensor_buffer_size; void getChunckData(uint8_t** gps,size_t* gps_size,uint8_t** sensor,size_t* sensor_size) { *gps = _gps_buffer; *sensor = _sensor_buffer; *gps_size = _gps_buffer_size; *sensor_size = _sensor_buffer_size; } #endif typedef enum { UNDEFINED_STREAM = 0, VIDEO_STREAM, AUDIO_STREAM, TXT_STREAM, } AVI_STREAM_TYPE; RMfile _file; AVIHeader _avi_header; // 파일헤더 stream_header_t _audioStreamHeader; stream_format_auds_t _audioStreamFormat; int _videoStreamCount; // 현재까지 로딩된 입력된 스트림 인덱스 stream_header_t _videoStreamHeaders[MAX_VIDEO_STREAM_COUNT]; // N개 stream_format_t _videoStreamFormat[MAX_VIDEO_STREAM_COUNT]; stream_header_t _txtStreamHeader; // TXT 스트림 헤더 int parse_riff(); int hex_dump_chunk(int chunk_len); #if (DEBUG_AVI_FORMAT) int parse_idx1(int chunk_len); #endif int read_avi_header(); // 메인 헤더 #if (SENSOR_AVI_SUBTITLE) int add_subtitle(long chunkSize); // 자막 처리 #endif void print_data_handler(unsigned char *handler); // Data Handler 출력 (DEBUG) int read_stream_header(stream_header_t *stream_header); int read_stream_format(stream_format_t *stream_format); int read_stream_format_auds(stream_format_auds_t *stream_format); //int read_strd_format(long strdSize); //int add_subtitle(long chunkSize); int parse_hdrl(unsigned int size); int parse_hdrl_list(); int parse_movi_list(unsigned int size); }; #endif // #if (FILE_FORMAT_AVI) #endif // RM_FORMAT_AVI_H