s60sc / ESP32-CAM_MJPEG2SD

ESP32 Camera motion capture application to record JPEGs to SD card as AVI files and stream to browser as MJPEG. If a microphone is installed then a WAV file is also created. Files can be uploaded via FTP or downloaded to browser.
GNU Affero General Public License v3.0
931 stars 214 forks source link

Re visiting AVI format thingy #381

Closed OldYin closed 8 months ago

OldYin commented 8 months ago

It appears that idxOffset[isTL] needs a value of 4 offset. Now .avi plays in all windows apps including VLC player with no errors. Indexes now look like results obtained from ffmpeg. Made a couple of changes in avi.cpp. Working for me but... over to you. :)

regards, Alex


void prepAviIndex(bool isTL) { // prep buffer to store index data, gets appended to end of file if (idxBuf[isTL] == NULL) idxBuf[isTL] = (uint8_t)ps_malloc((maxFrames+1)IDX_ENTRY); // include some space for audio index memcpy(idxBuf[isTL], idx1Buf, 4); // index header idxPtr[isTL] = CHUNK_HDR; // leave 4 bytes for index size moviSize[isTL] = indexLen[isTL] = 0; idxOffset[isTL]=4; //value 4 offset }

void buildAviHdr(uint8_t FPS, uint8_t frameType, uint16_t frameCnt, bool isTL) { // update AVI header template with file specific details size_t aviSize = moviSize[isTL] + AVI_HEADER_LEN + ((CHUNK_HDR+IDX_ENTRY) (frameCnt+(haveSoundFile?1:0))); // AVI content size // update aviHeader with relevant stats memcpy(aviHeader+4, &aviSize, 4); uint32_t usecs = (uint32_t)round(1000000.0f / FPS); // usecs_per_frame memcpy(aviHeader+0x20, &usecs, 4); memcpy(aviHeader+0x30, &frameCnt, 2); memcpy(aviHeader+0x8C, &frameCnt, 2); memcpy(aviHeader+0x84, &FPS, 1); uint32_t dataSize = moviSize[isTL] + ((frameCnt+(haveSoundFile?1:0)) CHUNK_HDR) + 4; memcpy(aviHeader+0x12E, &dataSize, 4); // data size

// apply video framesize to avi header memcpy(aviHeader+0x40, frameSizeData[frameType].frameWidth, 2); memcpy(aviHeader+0xA8, frameSizeData[frameType].frameWidth, 2); memcpy(aviHeader+0x44, frameSizeData[frameType].frameHeight, 2); memcpy(aviHeader+0xAC, frameSizeData[frameType].frameHeight, 2);

if INCLUDE_MIC

uint8_t withAudio = 2; // increase number of streams for audio if (isTL) memcpy(aviHeader+0x100, zeroBuf, 4); // no audio for timelapse else { if (haveSoundFile) memcpy(aviHeader+0x38, &withAudio, 1); memcpy(aviHeader+0x100, &audSize, 4); // audio data size } // apply audio details to avi header memcpy(aviHeader+0xF8, &SAMPLE_RATE, 4); uint32_t bytesPerSec = SAMPLE_RATE * 2; memcpy(aviHeader+0x104, &bytesPerSec, 4); // suggested buffer size memcpy(aviHeader+0x11C, &SAMPLE_RATE, 4); memcpy(aviHeader+0x120, &bytesPerSec, 4); // bytes per sec

else

memcpy(aviHeader+0x100, zeroBuf, 4);

endif

// reset state for next recording //moviSize[isTL] = idxOffset[isTL] = idxPtr[isTL] = 0;

moviSize[isTL] = idxPtr[isTL]=0; idxOffset[isTL]=4; //value 4 offset }


s60sc commented 8 months ago

Thanks - Ive updated the release with your changes

OldYin commented 8 months ago

Thank you for providing the makings of a pretty decent security monitor :)

Best wishes, Alex