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

309 lines
9.2 KiB
C++

#ifndef RM_FORMAT_MOV_H
#define RM_FORMAT_MOV_H
#if (FILE_FORMAT_MOV)
// 기본정보(duration + bitrate) 읽기 + 센서 파서
// 기존 mov_reader.h/cpp + rm_mov_format.h/cpp 통합 버전
#if !defined(BBEXTRACT)
#include "../rm_include.h"
#include <QString>
#endif
#include "rm_format.h"
extern "C" {
#include "fileio.h"
}
#include <stdint.h>
// 최대 tag 탐색 깊이
#define RM_MOV_MAX_DEPTH 10
// 마지막 탐색된 tag 의 최대 크기 (eg. 3개 trak 에서 mdia->stbl->stsd stsd 가 text 인 tag 탐색시
#if(RM_MODEL == RM_MODEL_TYPE_TB4000 || RM_MODEL == RM_MODEL_TYPE_MH9000)
#define RM_MOV_MAX_TAG_VALUE_SIZE 100
#else // 4000
#define RM_MOV_MAX_TAG_VALUE_SIZE 10
#endif // 4000
#if (RM_MODEL == RM_MODEL_TYPE_NX_DRW22)
typedef struct _GPS0
{
double lat; // 0
double lon; // 8
uint32_t alt; // 16
uint16_t speed; // 20
uint8_t year; // 22
uint8_t month; // 23
uint8_t day; // 24
uint8_t hour; // 25
uint8_t min; // 26
uint8_t sec; // 27
uint8_t degree; // 28
uint8_t status; // 29
uint8_t version; // 30
uint8_t reserved;
} GPS0;
#elif (RM_MODEL == RM_MODEL_TYPE_KEIYO1 || RM_MODEL == RM_MODEL_TYPE_MBJ5010 || RM_MODEL == RM_MODEL_TYPE_FC_DR232W || RM_MODEL == RM_MODEL_TYPE_BV2000)
// #define SENSOR_INTERVAL 1 // 2초 간격으로 저장
// #define SENSOR_FPS 40 // " 40개씩 저장됨
#define MAX_SENSOR_FPS 40
#endif // RM_MODEL_TYPE_NX_DRW22
#if (RM_MODEL == RM_MODEL_TYPE_TB4000)
//typedef struct GPSINFOCHUCKTIME_s
//{
// unsigned char byYear; // < Years since 1900
// unsigned char byMon; // < Months since January - [0,11]
// unsigned char byDay; // < Day of the month - [1,31]
// unsigned char byHour; // < Hours since midnight - [0,23]
// unsigned char byMin; // < Minutes after the hour - [0,59]
// unsigned char bySec; // < Seconds after the minute - [0,59]
//} GPSINFOCHUCKTIME;
typedef struct _GPSINFOCHUCK_TELEBIT
{
double dwLat; //< Latitude in NDEG - +/-[degree][min].[sec/60]
double dwLon; //< Longitude in NDEG - +/-[degree][min].[sec/60]
long lAlt; //< Altitude in meter +-:under/below sea level
unsigned short usSpeed; //< Speed unit: km/h
unsigned char datetime[6]; // byYear(from 1900), byMon, byDay, byHour, byMin, bySec
//GPSINFOCHUCKTIME sUTC; //< UTC of position
unsigned char ubDirection; //< Clockwise degree from the North.
unsigned char ubFlag; //< Check if the GPS data is valid;
unsigned char ubVersion; //< Stuture Version
unsigned char ubReserved;
} GPSINFOCHUCK_TELEBIT;
#endif // 4000
#if (RM_MODEL == RM_MODEL_TYPE_MH9000)
#pragma pack(push, 1)
typedef struct _gps_chunk_t
{
char header[4]; // id = "DVAL"
unsigned short year;
unsigned short mon;
unsigned short mday;
unsigned short hour;
unsigned short min;
unsigned short sec;
char vehicle_id[16];
char driver_id[16];
char rec_type; // 0:normal, 1:event
char event_gsensor;
char event_smoke;
char event_dsm;
char flag_seat_b;
char flag_side_b;
char flag_wink_l;
char flag_wink_r;
char flag_foot_b;
char flag_gron_b;
char blank_a[2];
char flag_smoke;
char flag_dsm;
char blank_b[2];
unsigned short speed;
unsigned short rpm;
unsigned short gps_speed;
char blank_c[2];
unsigned int latitude; // lat * 100000
unsigned int longitude; // long * 100000
unsigned short gx[10]; // (g x 100) 100ms x 10 = 1sec
unsigned short gy[10]; // (g x 100) 100ms x 10 = 1sec
unsigned short gz[10]; // (g x 100) 100ms x 10 = 1sec
char fw_version[16];
long lAlt; /**< Altitude in meter +-:under/below sea level*/
unsigned char ubDirection; /**< Clockwise degree from the North.*/
} gps_chunk_t;
#pragma pack(pop)
#endif // MH9000
class MOVFormat
{
// 재생시간 및 bitrate parser
private:
VideoReadMode _readMode; // 현재 모드
VideoPreInfo* _preInfo; // 기본 정보 (존재할 경우 ReadMode == PreInfo)
bool _isValid; // 센서 관련?
// Python..
unsigned int _offset;
RMfile _file;
private:
// parse 중지
bool _stop_parse;
// 탐색할 tag 리스트 (최대 depth = 10)
int _tag_count;
long _tag_list[RM_MOV_MAX_DEPTH];
// 탐색 tag (depth) offset
unsigned int _tag_offset_list[RM_MOV_MAX_DEPTH];
// 탐색 tag (depth) size
long _tag_size_list[RM_MOV_MAX_DEPTH];
// 탐색 중 확인할 value (자막의 경우 track 중 value 가 txt 인지 확인해야함)
char _tag_search_value[RM_MOV_MAX_TAG_VALUE_SIZE];
// 초기화
void init_parser();
void set_tags(const char* tag,...);
// 현재 tag value 가 _tag_search_value 와 동일한지 확인
bool check_tag_value(long atom_type, unsigned int offset, long size);
// 처음부터 끝까지 depth 0 에서 parse 시작
void parse_all();
// 센서 데이터만 parse
//void parse_sensor();
// bitrate 만 parse
#if !defined(BBEXTRACT)
#if (CHECK_VIDEO_BITRATE)
bool parse_bitrate();
#endif // CHECK_VIDEO_BITRATE
void parse_avc1(long offset, long size); // H264 Video
#endif // #if !defined(BBEXTRACT)
bool parse_duration();
bool parse_sensor();
#if (RM_MODEL == RM_MODEL_TYPE_XLDR_88 || SUB_MODEL_CARROT_EMT)
bool parse_buffer(uint8_t* buffer,long size);
#endif
// _tag 로 지정된 tag 의 옵셋 가져오기
void parse(unsigned int offset, unsigned int length, int depth = 0);
unsigned int get_tag_list_offset();
#if (RM_MODEL == RM_MODEL_TYPE_NX_DRW22)
GPS0* _gps0;
int16_t *_zyx; // 20201005 XYZ->ZYX 로 수정요청
#elif (RM_MODEL == RM_MODEL_TYPE_ADT_CAPS || \
RM_MODEL == RM_MODEL_TYPE_BV2000 || \
RM_MODEL == RM_MODEL_TYPE_XLDR_88 || \
RM_MODEL == RM_MODEL_TYPE_KEIYO1 || \
RM_MODEL == RM_MODEL_TYPE_MBJ5010 || \
RM_MODEL == RM_MODEL_TYPE_FC_DR232W)
void* _nmea; // NMEA INFO
void* _sens; // _SEN
#elif (RM_MODEL == RM_MODEL_TYPE_MH9000)
gps_chunk_t* _sens;
#elif (RM_MODEL_EMT_KR)
void* _nmea; // NMEA INFO
#endif
#if (RM_MODEL != RM_MODEL_TYPE_MH9000 && !RM_MODEL_EMT_KR)
int _gps0Count;
#endif // _sens 에 통합
int _gsenCount;
#if (RM_MODEL == RM_MODEL_TYPE_BV2000 ||\
RM_MODEL == RM_MODEL_TYPE_KEIYO1 ||\
RM_MODEL == RM_MODEL_TYPE_MBJ5010 ||\
RM_MODEL == RM_MODEL_TYPE_MH9000 || \
RM_MODEL == RM_MODEL_TYPE_FC_DR232W)
int _sensorFPS;
void process_subtitle(const char* subtitle);
#elif (RM_MODEL_EMT_KR)
void process_subtitle(const char* subtitle);
#endif
public:
MOVFormat(RMfile in,VideoReadMode mode = VideoReadSensor, VideoPreInfo* info = NULL);
static bool duration(RMfile in,VideoPreInfo* info);
#if !defined(BBEXTRACT)
#if (CHECK_VIDEO_BITRATE)
static bool movSize(RMfile in,VideoPreInfo* info);
#endif
#endif // #if !defined(BBEXTRACT)
~MOVFormat();
#if (RM_MODEL_EMT_KR)
QString modelName;
#endif
bool isValid()
{
return _isValid;
}
// MOV 크기와 재생시간 그리고 오디오 bitrate (kb/sec) 를 입력받아 mov bitrate 를 계산한다
#if (CHECK_VIDEO_BITRATE)
static int videoBitrate(VideoPreInfo* info) {
const double kb = 1000.0; // 1024?
const double durationInSec = (double)(info->duration) / 1000.0;
double videoSize = (double)(info->movSize);
return videoSize * 8.0 / durationInSec / kb;
}
#endif
#if (RM_MODEL == RM_MODEL_TYPE_NX_DRW22)
int getGPS(GPS0** gps)
{
*gps = _gps0;
return _gps0Count;
}
int getSensor(int16_t** sensor)
{
*sensor = _zyx;
return _gsenCount;
}
#elif (RM_MODEL_EMT_KR)
int getNMEA(void** nmea)
{
*nmea = _nmea;
return _gsenCount;
}
#elif (RM_MODEL == RM_MODEL_TYPE_ADT_CAPS || \
RM_MODEL == RM_MODEL_TYPE_XLDR_88 || \
RM_MODEL == RM_MODEL_TYPE_KEIYO1 || \
RM_MODEL == RM_MODEL_TYPE_MBJ5010 || \
RM_MODEL == RM_MODEL_TYPE_BV2000 || \
RM_MODEL == RM_MODEL_TYPE_MH9000 | \
RM_MODEL == RM_MODEL_TYPE_FC_DR232W)
// MH9000은 sensor 에 통합되어 있음
#if (RM_MODEL != RM_MODEL_TYPE_MH9000)
int getGPS(void** nmea)
{
*nmea = _nmea;
return _gps0Count;
}
#endif //
int getSensor(void** sensor)
{
*sensor = _sens;
return _gsenCount;
}
#if (RM_MODEL == RM_MODEL_TYPE_KEIYO1 || \
RM_MODEL == RM_MODEL_TYPE_MBJ5010 || \
RM_MODEL == RM_MODEL_TYPE_FC_DR232W || \
RM_MODEL == RM_MODEL_TYPE_BV2000 || \
RM_MODEL == RM_MODEL_TYPE_MH9000)
int getSensorFPS() {
return _sensorFPS;
}
#endif
#elif (RM_MODEL == RM_MODEL_TYPE_TB4000)
GPSINFOCHUCK_TELEBIT* _nmea; // NMEA INFO
int getGPS(GPSINFOCHUCK_TELEBIT** nmea)
{
*nmea = _nmea;
return _gps0Count;
}
#endif
};
#endif // #if (FILE_FORMAT_MOV)
#endif // RM_FORMAT_MOV_H