Browse Source

More robust AVI playing

Lou Yihua 6 years ago
parent
commit
71fa931095
7 changed files with 713 additions and 593 deletions
  1. 1 1
      audio.c
  2. 536 525
      aviplay.c
  3. 10 5
      aviplay.h
  4. 133 0
      riff.h
  5. 21 62
      sound.c
  6. 3 0
      win32/sdlpal.vcxproj
  7. 9 0
      win32/sdlpal.vcxproj.filters

+ 1 - 1
audio.c

@@ -171,7 +171,7 @@ AUDIO_FillBuffer(
    //
    // Play sound for AVI
    //
-   AVI_FillAudioBuffer(NULL, (LPBYTE)stream, len);
+   AVI_FillAudioBuffer(AVI_GetPlayState(), (LPBYTE)stream, len);
 
    //
    // Convert audio from native byte-order to actual byte-order

File diff suppressed because it is too large
+ 536 - 525
aviplay.c


+ 10 - 5
aviplay.h

@@ -38,14 +38,19 @@ PAL_AVIShutdown(
 
 BOOL
 PAL_PlayAVI(
-    LPCSTR     lpszPath
+    const char *lpszPath
 );
 
-VOID SDLCALL
+void SDLCALL
 AVI_FillAudioBuffer(
-    LPVOID          udata,
-    LPBYTE          stream,
-    INT             len
+    void       *udata,
+    uint8_t    *stream,
+    int         len
+);
+
+void *
+AVI_GetPlayState(
+	void
 );
 
 PAL_C_LINKAGE_END

+ 133 - 0
riff.h

@@ -0,0 +1,133 @@
+#ifndef PAL_RIFF_H
+#define PAL_RIFF_H
+
+#include <stdint.h>
+
+typedef struct RIFFHeader
+{
+	uint32_t signature;         /* 'RIFF' */
+	uint32_t length;            /* Total length minus eight, little-endian */
+	uint32_t type;              /* 'WAVE', 'AVI ', ... */
+} RIFFHeader;
+
+typedef struct RIFFChunkHeader
+{
+	uint32_t type;             /* 'fmt ', 'hdrl', 'movi' and so on */
+	uint32_t length;           /* Total chunk length minus eight, little-endian */
+} RIFFChunkHeader;
+
+typedef struct RIFFChunk
+{
+	RIFFChunkHeader header;
+	uint8_t         data[1];
+} RIFFChunk;
+
+typedef struct RIFFListHeader
+{
+	uint32_t signature;        /* 'LIST' */
+	uint32_t length;           /* Total list length minus eight, little-endian */
+	uint32_t type;             /* 'fmt ', 'hdrl', 'movi' and so on */
+} RIFFListHeader;
+
+typedef union RIFFBlockHeader
+{
+	struct {
+		uint32_t  type;
+		uint32_t  length;
+	};
+	RIFFChunkHeader chunk;
+	RIFFListHeader  list;
+} RIFFBlockHeader;
+
+typedef struct WAVEFormatPCM
+{
+	uint16_t wFormatTag;      /* format type */
+	uint16_t nChannels;       /* number of channels (i.e. mono, stereo, etc.) */
+	uint32_t nSamplesPerSec;  /* sample rate */
+	uint32_t nAvgBytesPerSec; /* for buffer estimation */
+	uint16_t nBlockAlign;     /* block size of data */
+	uint16_t wBitsPerSample;
+} WAVEFormatPCM;
+
+typedef struct WAVEFormatEx
+{
+	WAVEFormatPCM format;
+	uint16_t      cbSize;
+} WAVEFormatEx;
+
+typedef struct AVIMainHeader
+{
+	uint32_t      dwMicroSecPerFrame; // frame display rate (or 0)
+	uint32_t      dwMaxBytesPerSec; // max. transfer rate
+	uint32_t      dwPaddingGranularity; // pad to multiples of this size
+#define AVIF_HASINDEX        0x00000010 // Index at end of file?
+#define AVIF_MUSTUSEINDEX    0x00000020
+#define AVIF_ISINTERLEAVED   0x00000100
+	uint32_t      dwFlags; // the ever-present flags
+	uint32_t      dwTotalFrames; // # frames in file
+	uint32_t      dwInitialFrames;
+	uint32_t      dwStreams;
+	uint32_t      dwSuggestedBufferSize;
+	uint32_t      dwWidth;
+	uint32_t      dwHeight;
+	uint32_t      dwReserved[4];
+} AVIMainHeader;
+
+typedef struct AVIStreamHeader
+{
+	uint32_t      fccType;
+	uint32_t      fccHandler;
+	uint32_t      dwFlags;
+	uint16_t      wPriority;
+	uint16_t      wLanguage;
+	uint32_t      dwInitialFrames;
+	uint32_t      dwScale;
+	uint32_t      dwRate; /* dwRate / dwScale == samples/second */
+	uint32_t      dwStart;
+	uint32_t      dwLength; /* In units above... */
+	uint32_t      dwSuggestedBufferSize;
+	uint32_t      dwQuality;
+	uint32_t      dwSampleSize;
+	uint16_t      rcFrame[4];
+} AVIStreamHeader;
+
+typedef struct BitmapInfoHeader
+{
+	uint32_t      biSize;
+	uint32_t      biWidth;
+	uint32_t      biHeight;
+	uint16_t      biPlanes;
+	uint16_t      biBitCount;
+	uint32_t      biCompression;
+	uint32_t      biSizeImage;
+	uint32_t      biXPelsPerMeter;
+	uint32_t      biYPelsPerMeter;
+	uint32_t      biClrUsed;
+	uint32_t      biClrImportant;
+} BitmapInfoHeader;
+
+#define RIFF_RIFF (((uint32_t)'R') | (((uint32_t)'I') << 8) | (((uint32_t)'F') << 16) | (((uint32_t)'F') << 24))
+
+#define RIFF_WAVE (((uint32_t)'W') | (((uint32_t)'A') << 8) | (((uint32_t)'V') << 16) | (((uint32_t)'E') << 24))
+#define WAVE_fmt  (((uint32_t)'f') | (((uint32_t)'m') << 8) | (((uint32_t)'t') << 16) | (((uint32_t)' ') << 24))
+#define WAVE_data (((uint32_t)'d') | (((uint32_t)'a') << 8) | (((uint32_t)'t') << 16) | (((uint32_t)'a') << 24))
+
+#define RIFF_AVI  (((uint32_t)'A') | (((uint32_t)'V') << 8) | (((uint32_t)'I') << 16) | (((uint32_t)' ') << 24))
+#define AVI_hdrl  (((uint32_t)'h') | (((uint32_t)'d') << 8) | (((uint32_t)'r') << 16) | (((uint32_t)'l') << 24))
+#define AVI_strl  (((uint32_t)'s') | (((uint32_t)'t') << 8) | (((uint32_t)'r') << 16) | (((uint32_t)'l') << 24))
+#define AVI_strh  (((uint32_t)'s') | (((uint32_t)'t') << 8) | (((uint32_t)'r') << 16) | (((uint32_t)'h') << 24))
+#define AVI_strf  (((uint32_t)'s') | (((uint32_t)'t') << 8) | (((uint32_t)'r') << 16) | (((uint32_t)'f') << 24))
+#define AVI_avih  (((uint32_t)'a') | (((uint32_t)'v') << 8) | (((uint32_t)'i') << 16) | (((uint32_t)'h') << 24))
+#define AVI_LIST  (((uint32_t)'L') | (((uint32_t)'I') << 8) | (((uint32_t)'S') << 16) | (((uint32_t)'T') << 24))
+#define AVI_movi  (((uint32_t)'m') | (((uint32_t)'o') << 8) | (((uint32_t)'v') << 16) | (((uint32_t)'i') << 24))
+#define AVI_01wb  (((uint32_t)'0') | (((uint32_t)'1') << 8) | (((uint32_t)'w') << 16) | (((uint32_t)'b') << 24))
+#define AVI_00dc  (((uint32_t)'0') | (((uint32_t)'0') << 8) | (((uint32_t)'d') << 16) | (((uint32_t)'c') << 24))
+#define AVI_00db  (((uint32_t)'0') | (((uint32_t)'0') << 8) | (((uint32_t)'d') << 16) | (((uint32_t)'b') << 24))
+#define AVI_rec   (((uint32_t)'r') | (((uint32_t)'e') << 8) | (((uint32_t)'c') << 16) | (((uint32_t)' ') << 24))
+#define AVI_JUNK  (((uint32_t)'J') | (((uint32_t)'U') << 8) | (((uint32_t)'N') << 16) | (((uint32_t)'K') << 24))
+#define AVI_vids  (((uint32_t)'v') | (((uint32_t)'i') << 8) | (((uint32_t)'d') << 16) | (((uint32_t)'s') << 24))
+#define AVI_auds  (((uint32_t)'a') | (((uint32_t)'u') << 8) | (((uint32_t)'d') << 16) | (((uint32_t)'s') << 24))
+#define VIDS_MSVC (((uint32_t)'M') | (((uint32_t)'S') << 8) | (((uint32_t)'V') << 16) | (((uint32_t)'C') << 24))
+#define VIDS_msvc (((uint32_t)'m') | (((uint32_t)'s') << 8) | (((uint32_t)'v') << 16) | (((uint32_t)'c') << 24))
+
+#endif

+ 21 - 62
sound.c

@@ -28,6 +28,7 @@
 #include "util.h"
 #include "resampler.h"
 #include "midi.h"
+#include "riff.h"
 #include <math.h>
 
 #if PAL_HAS_OGG
@@ -74,32 +75,6 @@ typedef struct tagSOUNDPLAYER
 	int                 cursounds;
 } SOUNDPLAYER, *LPSOUNDPLAYER;
 
-typedef struct tagRIFFHEADER
-{
-	DWORD   riff_sig;		/* 'RIFF' */
-	DWORD   data_length;	/* Total length minus eight, little-endian */
-	DWORD   riff_type;		/* 'WAVE' */
-} RIFFHEADER, *LPRIFFHEADER;
-typedef const RIFFHEADER *LPCRIFFHEADER;
-
-typedef struct tagRIFFCHUNK
-{
-	DWORD   chunk_type;		/* 'fmt ' and so on */
-	DWORD   chunk_length;	/* Total chunk length minus eight, little-endian */
-} RIFFCHUNK, *LPRIFFCHUNK;
-typedef const RIFFCHUNK *LPCRIFFCHUNK;
-
-typedef struct tagWAVEFORMATPCM
-{
-	WORD    wFormatTag;        /* format type */
-	WORD    nChannels;         /* number of channels (i.e. mono, stereo, etc.) */
-	DWORD   nSamplesPerSec;    /* sample rate */
-	DWORD   nAvgBytesPerSec;   /* for buffer estimation */
-	WORD    nBlockAlign;       /* block size of data */
-	WORD    wBitsPerSample;
-} WAVEFORMATPCM, *LPWAVEFORMATPCM;
-typedef const WAVEFORMATPCM *LPCWAVEFORMATPCM;
-
 static const void *
 SOUND_LoadWAVEData(
 	LPCBYTE                lpData,
@@ -125,54 +100,42 @@ SOUND_LoadWAVEData(
     Pointer to the WAVE data inside the input buffer, NULL if failed.
 --*/
 {
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-#	define RIFF		0x52494646 // 'RIFF'
-#	define WAVE		0x57415645 // 'WAVE'
-#	define FMT		0x666D7420 // 'fmt '
-#	define DATA		0x64617461 // 'data'
-#	define PCM      0x0100
-#else
-#	define RIFF		0x46464952 // 'FFIR'
-#	define WAVE		0x45564157 // 'EVAW'
-#	define FMT		0x20746D66 // ' tmf'
-#	define DATA		0x61746164 // 'atad'
-#	define PCM      0x0001
-#endif
-	LPCRIFFHEADER lpRiff = (LPCRIFFHEADER)lpData;
-	LPCRIFFCHUNK lpChunk;
-	LPCWAVEFORMATPCM lpFormat = NULL;
-	LPCBYTE lpWaveData = NULL;
-	DWORD len;
-
-	if (dwLen < sizeof(RIFFHEADER) || lpRiff->riff_sig != RIFF || lpRiff->riff_type != WAVE || dwLen < SDL_SwapLE32(lpRiff->data_length) + 8)
+	const RIFFHeader      *lpRiff   = (const RIFFHeader *)lpData;
+	const RIFFChunkHeader *lpChunk  = NULL;
+	const WAVEFormatPCM   *lpFormat = NULL;
+	const uint8_t         *lpWaveData = NULL;
+	uint32_t len;
+
+	if (dwLen < sizeof(RIFFHeader) || lpRiff->signature != RIFF_RIFF ||
+		lpRiff->type != RIFF_WAVE || dwLen < SDL_SwapLE32(lpRiff->length) + 8)
 	{
 		return NULL;
 	}
 
-	lpChunk = (LPCRIFFCHUNK)(lpRiff + 1); dwLen -= sizeof(RIFFHEADER);
-	while (dwLen >= sizeof(RIFFCHUNK))
+	lpChunk = (const RIFFChunkHeader *)(lpRiff + 1); dwLen -= sizeof(RIFFHeader);
+	while (dwLen >= sizeof(RIFFChunkHeader))
 	{
-		len = SDL_SwapLE32(lpChunk->chunk_length);
-		if (dwLen >= sizeof(RIFFCHUNK) + len)
-			dwLen -= sizeof(RIFFCHUNK) + len;
+		len = SDL_SwapLE32(lpChunk->length);
+		if (dwLen >= sizeof(RIFFChunkHeader) + len)
+			dwLen -= sizeof(RIFFChunkHeader) + len;
 		else
 			return NULL;
 
-		switch (lpChunk->chunk_type)
+		switch (lpChunk->type)
 		{
-		case FMT:
-			lpFormat = (LPCWAVEFORMATPCM)(lpChunk + 1);
-			if (len != sizeof(WAVEFORMATPCM) || lpFormat->wFormatTag != PCM)
+		case WAVE_fmt:
+			lpFormat = (const WAVEFormatPCM *)(lpChunk + 1);
+			if (len != sizeof(WAVEFormatPCM) || lpFormat->wFormatTag != SDL_SwapLE16(0x0001))
 			{
 				return NULL;
 			}
 			break;
-		case DATA:
-			lpWaveData = (LPCBYTE)(lpChunk + 1);
+		case WAVE_data:
+			lpWaveData = (const uint8_t *)(lpChunk + 1);
 			dwLen = 0;
 			break;
 		}
-		lpChunk = (LPCRIFFCHUNK)((LPCBYTE)(lpChunk + 1) + len);
+		lpChunk = (const RIFFChunkHeader *)((const uint8_t *)(lpChunk + 1) + len);
 	}
 
 	if (lpFormat == NULL || lpWaveData == NULL)
@@ -187,10 +150,6 @@ SOUND_LoadWAVEData(
 	lpSpec->align = lpFormat->nChannels * lpFormat->wBitsPerSample >> 3;
 
 	return lpWaveData;
-
-#undef RIFF
-#undef WAVE
-#undef FMT
 }
 
 typedef struct tagVOCHEADER

+ 3 - 0
win32/sdlpal.vcxproj

@@ -300,6 +300,7 @@
     <ClCompile Include="..\aviplay.c" />
     <ClCompile Include="..\adplug\demuopl.cpp" />
     <ClCompile Include="..\audio.c" />
+    <ClCompile Include="..\aviplay.c" />
     <ClCompile Include="..\battle.c" />
     <ClCompile Include="..\ending.c" />
     <ClCompile Include="..\fight.c" />
@@ -400,6 +401,7 @@
     <ClInclude Include="..\adplug\dbopl.h" />
     <ClInclude Include="..\adplug\kemuopl.h" />
     <ClInclude Include="..\ascii.h" />
+    <ClInclude Include="..\aviplay.h" />
     <ClInclude Include="..\battle.h" />
     <ClInclude Include="..\codepage.h" />
     <ClInclude Include="..\common.h" />
@@ -470,6 +472,7 @@
     <ClInclude Include="..\res.h" />
     <ClInclude Include="..\resampler.h" />
     <ClInclude Include="..\players.h" />
+    <ClInclude Include="..\riff.h" />
     <ClInclude Include="..\rngplay.h" />
     <ClInclude Include="..\scene.h" />
     <ClInclude Include="..\script.h" />

+ 9 - 0
win32/sdlpal.vcxproj.filters

@@ -330,6 +330,9 @@
     <ClCompile Include="native_midi.cpp">
       <Filter>native_midi</Filter>
     </ClCompile>
+    <ClCompile Include="..\aviplay.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\ascii.h">
@@ -677,6 +680,12 @@
     <ClInclude Include="..\generated.h">
       <Filter>generated</Filter>
     </ClInclude>
+    <ClInclude Include="..\aviplay.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\riff.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\sdlpal.ico">