working on avi parsers

This commit is contained in:
2021-02-22 21:08:07 +01:00
parent 2e281f6d26
commit 2b35a340f9
5 changed files with 307 additions and 11 deletions

158
data/formats/avi/Demuxer.h Normal file
View File

@@ -0,0 +1,158 @@
#pragma once
#include "structs.h"
// https://docs.microsoft.com/en-us/previous-versions//ms779636(v=vs.85)?redirectedfrom=MSDN
namespace AVI {
template <typename Source> class Demuxer {
Source& src;
bool valid = true;
AVITypeHeader riff;
AVITypeHeader hdrl;
AVICommonHeader avih;
AVIMainHeader main_hdr;
struct State {
AVIStreamHeader streamHeaders[2];
struct Video {
uint32_t streamID;
BitMapInfoHeader fmt;
} video;
struct Audio {
uint32_t streamID;
WaveFormat fmt;
} audio;
ChunkInfo moviInfo;
ChunkInfo idxlInfo;
uint32_t totalSec;
} state;
public:
Demuxer(Source& src) : src(src) {
read(riff);
if (memcmp(riff.fourcc, "RIFF", 4) != 0) {valid = false; return;}
read(hdrl);
if (memcmp(hdrl.fourcc, "LIST", 4) != 0) {valid = false; return;}
if (memcmp(hdrl.type, "hdrl", 4) != 0) {valid = false; return;}
read(avih);
if (memcmp(avih.fourcc, "avih", 4) != 0) {valid = false; return;}
if (avih.length != sizeof(main_hdr)) {valid = false; return;}
read(main_hdr);
uint32_t posOfStreamStart = pos;
for (uint32_t i = 0; i < main_hdr.streams; ++i) {
bool curStreamIsVideo = false;
AVITypeHeader strl;
read(strl);
if (memcmp(strl.fourcc, "LIST", 4) != 0) {valid = false; return;}
if (memcmp(strl.type, "strl", 4) != 0) {valid = false; return;}
AVICommonHeader strh;
read(strh);
if (memcmp(strh.fourcc, "strh", 4) != 0) {valid = false; return;}
AVIStreamHeader stream_hdr;
read(stream_hdr);
if (memcmp(stream_hdr.type, "vids", 4) == 0) {
state.video.streamID = i;
state.streamHeaders[i] = stream_hdr;
curStreamIsVideo = true;
} else if (memcmp(stream_hdr.type, "auds", 4) == 0) {
state.audio.streamID = i;
state.streamHeaders[i] = stream_hdr;
} else {
valid = false; return;
}
AVICommonHeader strf;
read(strf);
if (curStreamIsVideo) {
BitMapInfoHeader bmih;
read(bmih);
state.video.fmt = bmih;
} else {
WaveFormat wf;
read(state.audio.fmt);
}
// seek to the next stream
seek(posOfStreamStart + 8 + strl.length);
}
AVITypeHeader movi;
state.moviInfo.offset = pos;
read(movi);
state.moviInfo.entry_offset = pos;
state.moviInfo.size = movi.length - 4;
seek(state.moviInfo.offset + 8 + movi.length);
AVITypeHeader idxl;
state.idxlInfo.offset = pos;
read(idxl);
state.idxlInfo.entry_offset = pos;
state.idxlInfo.size = idxl.length - 4;
// total length in seconds based on the video stream
// normally scale is 1 and rate = FPS
// for non-integer FPS, scale and rate vary accordingly
AVIStreamHeader& videoStreamHeader = state.streamHeaders[state.video.streamID];
state.totalSec = videoStreamHeader.length * videoStreamHeader.scale / videoStreamHeader.rate;
printf("nn");
// p->total_sec = avi_video_calc_seconds(avi_parser_get_video_header(p));
// goto end;
//seek(state.streamHeaders[state.video.streamID].start);
AVICommonHeader chead;
read(chead);
printf("nn");
}
bool isValid() const {
return valid;
}
private:
uint32_t pos = 0;
void seek(uint32_t newPos) {
pos = newPos;
}
template <typename T> void read(T& dst) {
read(sizeof(T), &dst);
}
/** read x bytes from the input into dst */
template <typename T> void read(uint32_t size, T* dst) {
src.read(pos, size, (uint8_t*)dst);
pos += size;
}
};
}

104
data/formats/avi/structs.h Normal file
View File

@@ -0,0 +1,104 @@
#pragma once
typedef uint8_t FOURCC[4];
struct AVICommonHeader {
FOURCC fourcc;
uint32_t length;
};
struct AVITypeHeader {
FOURCC fourcc;
uint32_t length;
FOURCC type;
};
struct AVIMainHeader {
uint32_t ms_per_frame;
uint32_t max_bytes_per_sec;
uint32_t padding_granularity;
uint32_t flags;
uint32_t total_frames;
uint32_t initial_frames;
uint32_t streams;
uint32_t suggested_buffer_size;
uint32_t width;
uint32_t height;
uint32_t reserved[4];
};
struct AVIStreamHeader {
//FOURCC fourcc;
//uint32_t length;
FOURCC type;
FOURCC fcc_handler;
uint32_t flags;
uint16_t priority;
uint16_t language;
uint32_t initial_frames;
uint32_t scale;
uint32_t rate;
uint32_t start;
uint32_t length;
uint32_t suggested_buffer_size;
uint32_t quality;
uint32_t sample_size;
struct {
uint16_t left;
uint16_t top;
uint16_t right;
uint16_t bottom;
} rcFrame;
};
struct BitMapInfoHeader {
uint32_t biSize;
int32_t biWidth;
int32_t biHeight;
int16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
};
struct RGBQUAD {
uint8_t rgbBlue;
uint8_t rgbGreen;
uint8_t rgbRed;
uint8_t rgbReserved;
};
struct BitMapInfo {
BitMapInfoHeader bmi_header;
RGBQUAD bmi_colors[1];
};
struct WaveFormat {
uint16_t format_tag;
uint16_t channels;
uint32_t samples_per_sec;
uint32_t avg_bytes_per_sec;
uint16_t block_align;
uint16_t size;
};
struct AVIIndexEntry {
uint32_t ckid;
uint32_t flags;
uint32_t chunk_offset;
uint32_t chunk_length;
};
struct ChunkInfo {
uint32_t offset;
uint32_t entry_offset;
uint32_t size;
};