#pragma once #include "structs.h" // https://docs.microsoft.com/en-us/previous-versions//ms779636(v=vs.85)?redirectedfrom=MSDN namespace AVI { template 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 void read(T& dst) { read(sizeof(T), &dst); } /** read x bytes from the input into dst */ template void read(uint32_t size, T* dst) { src.read(pos, size, (uint8_t*)dst); pos += size; } }; }