159 lines
3.4 KiB
C++
159 lines
3.4 KiB
C++
#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;
|
|
}
|
|
|
|
};
|
|
|
|
}
|