--- /dev/null
+/* BitReader.c */
+/* 2009/06/26 */
+
+#include "StdAfx.h"
+
+#include "BitReader.h"
+
+/* */
+
+#pragma warning(disable : 4799)
+
+/* */
+
+void QT_BitReader_C_Initialize(
+ BitReader_C_t* t,
+ const VOID* p,
+ SIZE_T size)
+{
+ t->Cache = 0;
+
+ t->Count = 16;
+
+ t->p = (const UINT8*)p;
+ t->end = t->p + size;
+}
+
+/* */
+
+void QT_BitReader_X86_Initialize(
+ BitReader_X86_t* t,
+ const VOID* p,
+ SIZE_T size)
+{
+ t->Cache = 0;
+
+ t->Count = 32;
+
+ t->p = (const UINT8*)p;
+ t->end = t->p + size;
+}
+
+/* */
+
+void QT_BitReader_MMX_Initialize(
+ BitReader_MMX_t* t,
+ const VOID* p,
+ SIZE_T size)
+{
+ t->Cache = _mm_setzero_si64();
+
+ t->Count = 32;
+
+ t->p = (const UINT8*)p;
+ t->end = t->p + size;
+}
+
+/* */
+
--- /dev/null
+/* BitReader.h */
+/* 2009/06/26 */
+
+#pragma once
+
+/* Generic C */
+
+struct QT_BitReader_C {
+
+ UINT32 Cache;
+
+ INT32 Count;
+
+ const UINT8* p;
+ const UINT8* end;
+
+};
+
+typedef struct QT_BitReader_C BitReader_C_t;
+
+void QT_BitReader_C_Initialize(
+ BitReader_C_t* t,
+ const VOID* p,
+ SIZE_T size);
+
+/* */
+
+#define INITIATE_BITS_C UINT32 bit_cache = d->Cache;
+#define FINALIZE_BITS_C d->Cache = bit_cache;
+
+#define LOAD_BITS_C \
+ if (d->Count > 0) { bit_cache |= ((d->p[0] << 8) | d->p[1]) << d->Count; d->p += 2; d->Count -= 16; }
+
+#define RETIRE_BITS_C(X) \
+ bit_cache <<= (X); d->Count += (X);
+
+#define GET_BITS_C(X) (bit_cache >> (32 - (X)))
+
+#define REST_BITS_C ((d->end - d->p) * 8 + (16 - d->Count))
+
+/* Generic X86 */
+
+struct QT_BitReader_X86 {
+
+ UINT64 Cache;
+
+ INT32 Count;
+
+ const UINT8* p;
+ const UINT8* end;
+
+};
+
+typedef struct QT_BitReader_X86 BitReader_X86_t;
+
+void QT_BitReader_X86_Initialize(
+ BitReader_X86_t* t,
+ const VOID* p,
+ SIZE_T size);
+
+/* */
+
+#define INITIATE_BITS_X86 UINT64 bit_cache = d->Cache;
+#define FINALIZE_BITS_X86 d->Cache = bit_cache;
+
+#define LOAD_BITS_X86 \
+ if (d->Count == 32) { bit_cache |= (UINT64) _byteswap_ulong(*((const UINT32*)(d->p))) << 32; d->p += 4; d->Count -= 32; } \
+ else if (d->Count > 0) { bit_cache |= __ll_lshift(_byteswap_ulong(*((const UINT32*)(d->p))), d->Count); d->p += 4; d->Count -= 32; }
+
+#define RETIRE_BITS_X86(X) \
+ bit_cache = __ll_lshift(bit_cache, (X)); d->Count += (X);
+
+#define GET_BITS_X86(X) ((UINT32)(bit_cache >> 32) >> (32 - (X)))
+
+#define REST_BITS_X86 ((d->end - d->p) * 8 + (32 - d->Count))
+
+/* MMX */
+
+struct QT_BitReader_MMX {
+
+ __m64 Cache;
+
+ INT32 Count;
+
+ const UINT8* p;
+ const UINT8* end;
+
+};
+
+typedef struct QT_BitReader_MMX BitReader_MMX_t;
+
+void QT_BitReader_MMX_Initialize(
+ BitReader_MMX_t* t,
+ const VOID* p,
+ SIZE_T size);
+
+/* */
+
+#define INITIATE_BITS_MMX __m64 bit_cache = d->Cache;
+#define FINALIZE_BITS_MMX d->Cache = bit_cache;
+
+#define LOAD_BITS_MMX \
+ if (d->Count > 0) { bit_cache = _mm_or_si64(bit_cache, _mm_sll_si64(_mm_cvtsi32_si64(_byteswap_ulong(*((const UINT32*)(d->p)))), _mm_cvtsi32_si64(d->Count))); d->p += 4; d->Count -= 32; }
+
+#define RETIRE_BITS_MMX(X) \
+ bit_cache = _mm_sll_si64(bit_cache, _mm_cvtsi32_si64(X)); d->Count += (X);
+
+#define RETIRE_BITS_I_MMX(X) \
+ bit_cache = _mm_slli_si64(bit_cache, (X)); d->Count += (X);
+
+#define GET_BITS_MMX(X) _mm_cvtsi64_si32(_mm_srl_si64(bit_cache, _mm_cvtsi32_si64(64 - (X))));
+
+#define GET_BITS_I_MMX(X) _mm_cvtsi64_si32(_mm_srli_si64(bit_cache, (64 - (X))));
+
+#define REST_BITS_MMX ((d->end - d->p) * 8 + (32 - d->Count))
+
+/* */
+
+#define FETCH_BITS_I(L, X) LOAD_BITS L = GET_BITS_I(X); RETIRE_BITS_I(X)
+#define FETCH_BITS(L, X) LOAD_BITS L = GET_BITS(X); RETIRE_BITS(X)
+
+#define RESUME_BITS bit_cache = d->Cache;
+
+/* */
+
--- /dev/null
+/* MemoryPool.c */
+/* 2009/05/14 */
+
+#include "StdAfx.h"
+
+#include "MemoryPool.h"
+
+struct MemoryBlock;
+
+typedef struct MemoryBlock MemoryBlock_t;
+
+struct MemoryBlock {
+
+ MemoryBlock_t* Next;
+
+ SIZE_T Size;
+
+ UINT32 Padding[2];
+
+};
+
+/* */
+
+void QT_MemoryPool_Init(
+ MemoryPool_t* t)
+{
+ t->Block = NULL;
+ t->TotalSize = 0;
+}
+
+void QT_MemoryPool_Release(
+ MemoryPool_t* t)
+{
+ MemoryBlock_t* p = (MemoryBlock_t*)(t->Block);
+ while (p != NULL) {
+ MemoryBlock_t* n = p->Next;
+ _aligned_free(p);
+ p = n;
+ }
+
+ t->Block = NULL;
+ t->TotalSize = 0;
+}
+
+VOID* QT_MemoryPool_Allocate(
+ MemoryPool_t* t,
+ SIZE_T cb)
+{
+ MemoryBlock_t* b = (MemoryBlock_t*)_aligned_malloc(
+ sizeof(MemoryBlock_t) + cb,
+ 0x10);
+ if (b == NULL) {
+ return NULL;
+ }
+
+ b->Next = t->Block;
+ b->Size = cb;
+
+ t->Block = b;
+ t->TotalSize += cb;
+
+ return b + 1;
+}
+
+/* */
+
--- /dev/null
+/* MemoryPool.h */
+/* 2009/05/14 */
+
+#pragma once
+
+/* MemoryPool */
+struct MemoryPool {
+
+ VOID* Block;
+ SIZE_T TotalSize;
+
+}; /* MemoryPool */
+
+typedef struct MemoryPool MemoryPool_t;
+
+/* */
+
+void QT_MemoryPool_Init(
+ MemoryPool_t* t);
+
+void QT_MemoryPool_Release(
+ MemoryPool_t* t);
+
+void* QT_MemoryPool_Allocate(
+ MemoryPool_t* t,
+ SIZE_T cb);
+
+/* */
+
--- /dev/null
+/* QTheoraArch.h */
+/* 2009/06/26 */
+
+#undef BitReader_t
+
+#undef INITIATE_BITS
+#undef FINALIZE_BITS
+#undef LOAD_BITS
+#undef RETIRE_BITS_I
+#undef RETIRE_BITS
+#undef GET_BITS_I
+#undef GET_BITS
+#undef REST_BITS
+
+#if defined(ARCH_C)
+
+#define BitReader_t BitReader_C_t
+
+#define INITIATE_BITS INITIATE_BITS_C
+#define FINALIZE_BITS FINALIZE_BITS_C
+
+#define LOAD_BITS LOAD_BITS_C
+#define RETIRE_BITS_I(X) RETIRE_BITS_C(X)
+#define RETIRE_BITS(X) RETIRE_BITS_C(X)
+#define GET_BITS_I(X) GET_BITS_C(X)
+#define GET_BITS(X) GET_BITS_C(X)
+#define REST_BITS REST_BITS_C
+
+#elif defined(ARCH_X86)
+
+#define BitReader_t BitReader_X86_t
+
+#define INITIATE_BITS INITIATE_BITS_X86
+#define FINALIZE_BITS FINALIZE_BITS_X86
+
+#define LOAD_BITS LOAD_BITS_X86
+#define RETIRE_BITS_I(X) RETIRE_BITS_X86(X)
+#define RETIRE_BITS(X) RETIRE_BITS_X86(X)
+#define GET_BITS_I(X) GET_BITS_X86(X)
+#define GET_BITS(X) GET_BITS_X86(X)
+#define REST_BITS REST_BITS_X86
+
+#elif defined(ARCH_MMX)
+
+#define BitReader_t BitReader_MMX_t
+
+#define INITIATE_BITS INITIATE_BITS_MMX
+#define FINALIZE_BITS FINALIZE_BITS_MMX
+
+#define LOAD_BITS LOAD_BITS_MMX
+#define RETIRE_BITS_I(X) RETIRE_BITS_I_MMX(X)
+#define RETIRE_BITS(X) RETIRE_BITS_MMX(X)
+#define GET_BITS_I(X) GET_BITS_I_MMX(X)
+#define GET_BITS(X) GET_BITS_MMX(X)
+#define REST_BITS REST_BITS_MMX
+
+#elif defined(ARCH_SSE2)
+
+
+#else
+
+#error "define ARCH_*"
+
+#endif
+
--- /dev/null
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="QTheoraEx"
+ ProjectGUID="{2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}"
+ RootNamespace="QTheoraEx"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="\83\\81[\83X \83t\83@\83C\83\8b"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\BitReader.c"
+ >
+ </File>
+ <File
+ RelativePath=".\MemoryPool.c"
+ >
+ </File>
+ <File
+ RelativePath=".\SetupDecoder.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AssemblerOutput="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AssemblerOutput="2"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\StdAfx.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\TheoraDecoder.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="\83w\83b\83_\81[ \83t\83@\83C\83\8b"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\BitReader.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MemoryPool.h"
+ >
+ </File>
+ <File
+ RelativePath=".\QTheoraArch.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SetupDecoder.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SetupDecoder_Impl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\StdAfx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\TheoraDecoder.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="\83\8a\83\\81[\83X \83t\83@\83C\83\8b"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
--- /dev/null
+/* SetupDecoder.c */
+/* 2009/06/26 */
+
+#include "StdAfx.h"
+
+#include "SetupDecoder.h"
+
+/* */
+
+#pragma warning(disable : 4799)
+
+/* */
+
+static INT32 ilog(UINT32 n)
+{
+ static const INT32 LOG2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 };
+
+ if (n < (1U << 14)) {
+ if (n < (1U << 4)) return 0 + LOG2_4[n ];
+ else if (n < (1U << 9)) return 5 + LOG2_4[n >> 5];
+ else return 10 + LOG2_4[n >> 10];
+
+ } else if (n < (1U << 24)) {
+ if (n < (1U << 19)) return 15 + LOG2_4[n >> 15];
+ else return 20 + LOG2_4[n >> 20];
+
+ } else if (n < (1U << 29)) {
+ return 25 + LOG2_4[n >> 25];
+
+ } else if (n < (1U << 31)) {
+ return 30 + LOG2_4[n >> 30];
+ }
+
+ return 0;
+}
+
+/* */
+
+/* HuffmanEntry */
+struct HuffmanEntry {
+
+ UINT32 Code;
+ UINT8 Length;
+ UINT8 Token;
+
+}; /* HuffmanEntry */
+
+typedef struct HuffmanEntry HuffmanEntry_t;
+
+static int compare(const void* a, const void* b)
+{
+ const HuffmanEntry_t* aa = (const HuffmanEntry_t*)a;
+ const HuffmanEntry_t* bb = (const HuffmanEntry_t*)b;
+
+ if (aa->Length < bb->Length) {
+ return -1;
+ }
+ if (aa->Length > bb->Length) {
+ return 1;
+ }
+
+ if (aa->Code < bb->Code) {
+ return -1;
+ }
+ if (aa->Code > bb->Code) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void Huffman_MakeDecoder(
+ HuffmanDecoder_t* d,
+ const HuffmanTable_t* t)
+{
+ HuffmanEntry_t entries[HUFFMAN_SIZE];
+
+ INT32 i, p, max;
+ const HuffmanEntry_t* e;
+
+ d->LookupBits = 0;
+ d->LookupToken = NULL;
+ d->LookupLength = NULL;
+
+ for (i = 0; i < HUFFMAN_SIZE; i++) {
+ entries[i].Code = t->Code[i];
+ entries[i].Length = t->Length[i];
+ entries[i].Token = t->Index[i];
+ }
+
+ qsort(
+ entries,
+ HUFFMAN_SIZE,
+ sizeof(HuffmanEntry_t),
+ compare);
+
+ max = 0;
+
+ p = 0;
+ e = entries;
+ for (i = 0; i < BITS_COUNT; i++) {
+ INT32 len = i + 1;
+
+ INT32 idx = p;
+
+ while (e->Length == len && p < HUFFMAN_SIZE) {
+ d->Code [p] = e->Code;
+ d->Token[p] = e->Token;
+
+ p++;
+ e++;
+ }
+
+ if (p - idx > 0) {
+ max = len;
+ d->Index[i] = idx;
+ } else {
+ d->Index[i] = -1;
+ }
+
+ d->Count[i] = p - idx;
+ }
+
+ for (i = max; i < BITS_COUNT; i++) {
+ d->Index[i] = -1;
+ d->Count[i] = -1;
+ }
+}
+
+static BOOL Huffman_MakeLookupTable(
+ HuffmanDecoder_t* d,
+ const HuffmanTable_t* t,
+ MemoryPool_t* pool,
+ INT32 bits)
+{
+ INT32 i;
+
+ UINT32 size = 1 << bits;
+
+ d->LookupBits = bits;
+
+ d->LookupToken = (INT8*)QT_MemoryPool_Allocate(pool, sizeof(INT) * size);
+ d->LookupLength = (INT8*)QT_MemoryPool_Allocate(pool, sizeof(INT) * size);
+
+ if (d->LookupToken == NULL || d->LookupLength == NULL) {
+ return FALSE;
+ }
+
+ memset(d->LookupToken, 0, size);
+ memset(d->LookupLength, 0, size);
+
+ for (i = 0; i < HUFFMAN_SIZE; i++) {
+ if (t->Length[i] <= bits) {
+ INT32 s = bits - t->Length[i];
+ INT32 n = 1 << s;
+
+ UINT32 base = t->Code[i] << s;
+
+ INT32 j;
+ for (j = 0; j < n; j++) {
+ UINT32 idx = base + j;
+ d->LookupToken [idx] = t->Index[i];
+ d->LookupLength[idx] = t->Length[i];
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/* */
+
+#define ARCH_C
+
+#include "QTheoraArch.h"
+
+#define IdentifyHeader_Decode IdentifyHeader_Decode_C
+#define Filter_Decode Filter_Decode_C
+#define Dequantize_Decode Dequantize_Decode_C
+#define Huffman_Decode Huffman_Decode_C
+#define SetupHeader_Decode SetupHeader_Decode_C
+
+#define QT_SetupDecoderSetupLacing QT_SetupDecoderSetupLacing_C
+
+#include "SetupDecoder_Impl.h"
+
+#undef ARCH_C
+
+/* */
+
+#define ARCH_X86
+
+#include "QTheoraArch.h"
+
+#define IdentifyHeader_Decode IdentifyHeader_Decode_X86
+#define Filter_Decode Filter_Decode_X86
+#define Dequantize_Decode Dequantize_Decode_X86
+#define Huffman_Decode Huffman_Decode_X86
+#define SetupHeader_Decode SetupHeader_Decode_X86
+
+#define QT_SetupDecoderSetupLacing QT_SetupDecoderSetupLacing_X86
+
+#include "SetupDecoder_Impl.h"
+
+#undef ARCH_X86
+
+/* */
+
+#define ARCH_MMX
+
+#include "QTheoraArch.h"
+
+#define IdentifyHeader_Decode IdentifyHeader_Decode_MMX
+#define Filter_Decode Filter_Decode_MMX
+#define Dequantize_Decode Dequantize_Decode_MMX
+#define Huffman_Decode Huffman_Decode_MMX
+#define SetupHeader_Decode SetupHeader_Decode_MMX
+
+#define QT_SetupDecoderSetupLacing QT_SetupDecoderSetupLacing_MMX
+
+#include "SetupDecoder_Impl.h"
+
+#undef ARCH_MMX
+
+/* */
+
--- /dev/null
+/* SetupDecoder.h */
+/* 2009/06/26 */
+
+#pragma once
+
+#include "BitReader.h"
+
+#include "MemoryPool.h"
+
+/* QT_IdentifyHeader */
+struct QT_IdentifyHeader {
+
+ UINT8 Version[4];
+
+ INT32 MX;
+ INT32 MY;
+
+ INT32 PCX;
+ INT32 PCY;
+ INT32 PDX;
+ INT32 PDY;
+
+ UINT32 FRN;
+ UINT32 FRD;
+
+ UINT32 PRN;
+ UINT32 PRD;
+
+ INT32 NOMBR;
+
+ UINT8 CS;
+ UINT8 QUAL;
+ UINT8 KFGSHIFT;
+ UINT8 PF;
+
+}; /* QT_IdentifyHeader */
+
+typedef struct QT_IdentifyHeader IdentifyHeader_t;
+
+/* FilterTable */
+struct FilterTable {
+
+ UINT8 Limit[64];
+
+}; /* FilterTable */
+
+typedef struct FilterTable FilterTable_t;
+
+/* DequantizeTable */
+struct DequantizeTable {
+
+ UINT16 ACScale[64];
+ UINT16 DCScale[64];
+
+ UINT8 Matrix[384][64];
+
+ UINT8 Count[2][3];
+
+ UINT8 Size[2][3][64];
+ UINT16 Base[2][3][64];
+
+}; /* DequantizeTable */
+
+typedef struct DequantizeTable DequantizeTable_t;
+
+/* */
+
+#define HUFFMAN_SIZE 32
+#define BITS_COUNT 32
+
+/* QT_HuffmanTable */
+struct QT_HuffmanTable {
+
+ UINT32 Code [HUFFMAN_SIZE];
+ UINT8 Length[HUFFMAN_SIZE];
+ UINT8 Index [HUFFMAN_SIZE];
+
+}; /* QT_HuffmanTable */
+
+typedef struct QT_HuffmanTable HuffmanTable_t;
+
+/* QT_HuffmanDecoder */
+struct QT_HuffmanDecoder {
+
+ INT8 Index[BITS_COUNT];
+ INT8 Count[BITS_COUNT];
+ UINT32 Code [HUFFMAN_SIZE];
+ UINT8 Token[HUFFMAN_SIZE];
+
+ INT32 LookupBits;
+ INT8* LookupToken;
+ INT8* LookupLength;
+
+}; /* QT_HuffmanDecoder */
+
+typedef struct QT_HuffmanDecoder HuffmanDecoder_t;
+
+/* */
+
+/* QT_SetupHeader */
+struct QT_SetupHeader {
+
+ FilterTable_t Filter;
+
+ DequantizeTable_t Dequantize;
+
+ HuffmanDecoder_t Huffman[80];
+
+}; /* QT_SetupHeader */
+
+typedef struct QT_SetupHeader SetupHeader_t;
+
+/* */
+
+BOOL QT_SetupDecoderSetupLacing_C(
+ IdentifyHeader_t* id,
+ SetupHeader_t* setup,
+ MemoryPool_t* pool,
+ BitReader_C_t* d);
+
+BOOL QT_SetupDecoderSetupLacing_X86(
+ IdentifyHeader_t* id,
+ SetupHeader_t* setup,
+ MemoryPool_t* pool,
+ BitReader_X86_t* d);
+
+BOOL QT_SetupDecoderSetupLacing_MMX(
+ IdentifyHeader_t* id,
+ SetupHeader_t* setup,
+ MemoryPool_t* pool,
+ BitReader_MMX_t* d);
+
+/* */
+
--- /dev/null
+/* SetupDecoder_Impl.h */
+/* 2009/06/26 */
+
+/* */
+
+static BOOL IdentifyHeader_Decode(
+ IdentifyHeader_t* t,
+ BitReader_t* d)
+{
+ INITIATE_BITS
+
+ INT32 hi, lo;
+
+ FETCH_BITS_I(t->Version[0], 8)
+ FETCH_BITS_I(t->Version[1], 8)
+ FETCH_BITS_I(t->Version[2], 8)
+
+ t->Version[3] = 0;
+
+ if (t->Version[0] != 3 || t->Version[1] != 2) {
+ return FALSE;
+ }
+
+ FETCH_BITS_I(t->MX, 16)
+ FETCH_BITS_I(t->MY, 16)
+
+ FETCH_BITS_I(hi, 8)
+ FETCH_BITS_I(lo, 16)
+ t->PCX = (hi << 16) | lo;
+
+ FETCH_BITS_I(hi, 8)
+ FETCH_BITS_I(lo, 16)
+ t->PCY = (hi << 16) | lo;
+
+ FETCH_BITS_I(t->PDX, 8)
+ FETCH_BITS_I(t->PDY, 8)
+
+ if (t->MX <= 0 || t->MY <= 0) {
+ return FALSE;
+ }
+
+ if (t->PCX <= 0 || t->PCX > t->MX * 16) {
+ return FALSE;
+ }
+
+ if (t->PCY <= 0 || t->PCY > t->MY * 16) {
+ return FALSE;
+ }
+
+ if (t->PDX > t->MX * 16 - t->PCX) {
+ return FALSE;
+ }
+
+ if (t->PDY > t->MY * 16 - t->PCY) {
+ return FALSE;
+ }
+
+ FETCH_BITS_I(hi, 16)
+ FETCH_BITS_I(lo, 16)
+ t->FRN = (hi << 16) | lo;
+
+ FETCH_BITS_I(hi, 16)
+ FETCH_BITS_I(lo, 16)
+ t->FRD = (hi << 16) | lo;
+
+ if (t->FRN == 0 || t->FRD == 0) {
+ return FALSE;
+ }
+
+ FETCH_BITS_I(hi, 8)
+ FETCH_BITS_I(lo, 16)
+ t->PRN = (hi << 16) | lo;
+
+ FETCH_BITS_I(hi, 8)
+ FETCH_BITS_I(lo, 16)
+ t->PRD = (hi << 16) | lo;
+
+ if ((t->PRN != 0 || t->PRD != 0) &&
+ (t->PRN == 0 || t->PRD == 0)) {
+ return FALSE;
+ }
+
+ FETCH_BITS_I(t->CS, 8)
+
+ FETCH_BITS_I(hi, 8)
+ FETCH_BITS_I(lo, 16)
+ t->NOMBR = (hi << 16) | lo;
+
+ FETCH_BITS_I(t->QUAL, 6)
+ FETCH_BITS_I(t->KFGSHIFT, 5)
+ FETCH_BITS_I(t->PF, 2)
+
+ if (t->PF != 0) { /* 4:2:0 */
+ return FALSE;
+ }
+
+ FETCH_BITS_I(lo, 3)
+ if (lo != 0) {
+ return FALSE;
+ }
+
+ FINALIZE_BITS
+
+ if (REST_BITS < 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* */
+
+static BOOL Filter_Decode(
+ FilterTable_t* t,
+ BitReader_t* d)
+{
+ INITIATE_BITS
+
+ INT32 i, bits;
+
+ FETCH_BITS_I(bits, 3)
+
+ for (i = 0; i < 64; i++) {
+ FETCH_BITS(t->Limit[i], bits)
+ }
+
+ FINALIZE_BITS
+
+ if (REST_BITS < 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* */
+
+static BOOL Dequantize_Decode(
+ DequantizeTable_t* t,
+ BitReader_t* d)
+{
+ INITIATE_BITS
+
+ INT32 i, j, n;
+ INT32 bits;
+
+ /* */
+
+ FETCH_BITS_I(bits, 4) bits++;
+ for (i = 0; i < 64; i++) {
+ FETCH_BITS(t->ACScale[i], bits)
+ }
+
+ FETCH_BITS_I(bits, 4) bits++;
+ for (i = 0; i < 64; i++) {
+ FETCH_BITS(t->DCScale[i], bits)
+ }
+
+ FETCH_BITS_I(n, 9) n++;
+ if (n >= 384) {
+ return FALSE;
+ }
+
+ for (j = 0; j < n; j++) {
+ for (i = 0; i < 64; i++) {
+ FETCH_BITS_I(t->Matrix[j][i], 8)
+ }
+ }
+
+ /* */
+
+ bits = ilog(n - 1);
+
+ for (j = 0; j < 2; j++) {
+ for (i = 0; i < 3; i++) {
+ INT32 nq = 1;
+ if (j > 0 || i > 0) {
+ FETCH_BITS_I(nq, 1)
+ }
+
+ if (nq != 0) {
+ INT32 qri = 0;
+ INT32 qi = 0;
+
+ for (; ; ) {
+ INT32 x, y;
+
+ FETCH_BITS(x, bits)
+ if (x >= n) {
+ return FALSE;
+ }
+
+ t->Base[j][i][qri] = x;
+
+ if (qi >= 63) {
+ break;
+ }
+
+ y = ilog(63 - qi);
+
+ FETCH_BITS(x, y) x++;
+
+ t->Size[j][i][qri] = x;
+
+ qri += 1;
+ qi += x;
+ }
+
+ if (qi >= 64) {
+ return FALSE;
+ }
+
+ t->Count[j][i] = qri;
+
+ } else {
+ INT32 q, p;
+
+ INT32 x = 0;
+ if (j > 0) {
+ FETCH_BITS_I(x, 1)
+ }
+
+ if (x != 0) {
+ q = 0;
+ p = i;
+ } else {
+ q = (3 * j + i - 1) / 3;
+ p = (i + 2) % 3;
+ }
+
+ t->Count[j][i] = t->Count[q][p];
+ memcpy(t->Size[j][i], t->Size[q][p], sizeof(t->Size[0][0]));
+ memcpy(t->Base[j][i], t->Base[q][p], sizeof(t->Base[0][0]));
+ }
+ }
+ }
+
+ FINALIZE_BITS
+
+ if (REST_BITS < 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* */
+
+static BOOL Huffman_Decode(
+ HuffmanTable_t* t,
+ BitReader_t* d)
+{
+ INITIATE_BITS
+
+ INT32 i = 0;
+
+ UINT32 bits = 0;
+ INT32 len = 0;
+
+ for (; ; ) {
+ INT32 x;
+ FETCH_BITS_I(x, 1)
+
+ if (x == 0) {
+ if (len >= 32) {
+ return FALSE;
+ }
+
+ bits <<= 1;
+ len += 1;
+
+ } else {
+ if (i >= HUFFMAN_SIZE) {
+ return FALSE;
+ }
+
+ t->Code [i] = bits;
+ t->Length[i] = len;
+
+ FETCH_BITS_I(t->Index[i], 5);
+
+ i++;
+
+ for (; ; ) {
+ if (len == 0) {
+ if (i != HUFFMAN_SIZE) {
+ return FALSE;
+ }
+
+ FINALIZE_BITS
+
+ if (REST_BITS < 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ if ((bits & 1) == 0) {
+ bits |= 1;
+ break;
+
+ } else {
+ bits >>= 1;
+ len -= 1;
+ }
+ }
+ }
+ }
+}
+
+/* */
+
+static BOOL SetupHeader_Decode(
+ SetupHeader_t* t,
+ MemoryPool_t* pool,
+ BitReader_t* d)
+{
+ INT32 i;
+
+ if (!Filter_Decode(
+ &(t->Filter),
+ d)) {
+ return FALSE;
+ }
+
+ if (!Dequantize_Decode(
+ &(t->Dequantize),
+ d)) {
+ return FALSE;
+ }
+
+ for (i = 0; i < 80; i++) {
+ HuffmanTable_t ht;
+ HuffmanDecoder_t* hd = t->Huffman + i;
+
+ if (!Huffman_Decode(&ht, d)) {
+ return FALSE;
+ }
+
+#if 0
+ {
+ INT32 j;
+ printf("HT:%2d\n", i);
+ for (j = 0; j < HUFFMAN_SIZE; j++) {
+ printf("0x%08X : %2d : %2d\n", ht.Code[j], ht.Length[j], ht.Index[j]);
+ }
+ }
+#endif
+
+ Huffman_MakeDecoder(hd, &ht);
+
+ if (!Huffman_MakeLookupTable(
+ hd,
+ &ht,
+ pool,
+ 10)) {
+ return FALSE;
+ }
+ }
+
+ if (REST_BITS < 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* */
+
+BOOL QT_SetupDecoderSetupLacing(
+ IdentifyHeader_t* id,
+ SetupHeader_t* setup,
+ MemoryPool_t* pool,
+ BitReader_t* d)
+{
+ INITIATE_BITS
+
+ static const char* ID = "theora";
+
+ UINT8 by;
+ INT32 i, j, p = 0;
+ INT32 sz[3] = { 0 };
+
+ INT32 size = d->end - d->p;
+
+ FETCH_BITS_I(by, 8) p++;
+ if (by != 2) {
+ return FALSE;
+ }
+
+ for (i = 0; i < 2; i++) {
+ for (; ; ) {
+ FETCH_BITS_I(by, 8) p++;
+
+ sz[i] += by;
+
+ if (by != 0xff) {
+ break;
+ }
+ }
+ }
+
+ sz[2] = (size - p) - (sz[0] + sz[1]);
+ if (sz[2] <= 0) {
+ return FALSE;
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (sz[i] < 7) {
+ return FALSE;
+ }
+
+ FETCH_BITS_I(by, 8)
+ if (by != 0x80 + i) {
+ return FALSE;
+ }
+
+ for (j = 0; j < 6; j++) {
+ FETCH_BITS_I(by, 8)
+ if (by != ID[j]) {
+ return FALSE;
+ }
+ }
+
+ switch (i) {
+ case 0: /* ID */
+ FINALIZE_BITS
+
+ if (!IdentifyHeader_Decode(
+ id,
+ d)) {
+ return FALSE;
+ }
+
+ RESUME_BITS
+ break;
+
+ case 1: /* COMM */
+ for (j = 0; j < sz[1] - 7; j++) {
+ FETCH_BITS_I(by, 8)
+ }
+ break;
+
+ case 2: /* SETUP */
+ FINALIZE_BITS
+
+ if (!SetupHeader_Decode(
+ setup,
+ pool,
+ d)) {
+ return FALSE;
+ }
+
+ RESUME_BITS
+ break;
+ }
+ }
+
+ FINALIZE_BITS
+
+ if (REST_BITS >= 8) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* */
+
+#undef IdentifyHeader_Decode
+#undef Filter_Decode
+#undef Dequantize_Decode
+#undef Huffman_Decode
+#undef SetupHeader_Decode
+
+#undef QT_SetupDecoderSetupLacing
+
+/* */
+
--- /dev/null
+/* StdAfx.c */
+/* 2009/06/26 */
+
+#include "StdAfx.h"
+
--- /dev/null
+/* StdAfx.h */
+/* 2009/06/26 */
+
+#pragma once
+
+#include <windows.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#define _USE_MATH_DEFINES
+
+#include <math.h>
+
+#include <intrin.h>
+#include <mmintrin.h>
+#include <xmmintrin.h>
+#include <emmintrin.h>
+
+#define ALIGN(X) _declspec(align(X))
+
--- /dev/null
+/* TheoraDecoder.c */
+/* 2009/06/26 */
+
+#include "StdAfx.h"
+
+#include "TheoraDecoder.h"
+
+#include "SetupDecoder.h"
+
+/* */
+
+BOOL g_QT_Available_SSE2 = FALSE;
+
+BOOL g_QT_Enable_X86 = TRUE;
+BOOL g_QT_Enable_MMX = FALSE;
+BOOL g_QT_Enable_SSE2 = FALSE;
+
+BOOL QT_Initialize(void)
+{
+ INT32 info[4] = { 0 };
+
+ __cpuid(info, 1);
+
+ if ((info[3] & (1 << 23)) != 0) {
+ g_QT_Enable_MMX = TRUE;
+ }
+
+ if ((info[3] & (1 << 26)) != 0) {
+ g_QT_Available_SSE2 = TRUE;
+ g_QT_Enable_SSE2 = TRUE;
+ }
+
+ return TRUE;
+}
+
+BOOL QT_SetEnableX86(BOOL b)
+{
+ BOOL e = g_QT_Enable_X86;
+
+ g_QT_Enable_X86 = b;
+
+ return e;
+}
+
+BOOL QT_SetEnableMMX(BOOL b)
+{
+ BOOL e = g_QT_Enable_MMX;
+
+ g_QT_Enable_MMX = b;
+
+ return e;
+}
+
+BOOL QT_SetEnableSSE2(BOOL b)
+{
+ BOOL e = g_QT_Enable_SSE2;
+
+ g_QT_Enable_SSE2 = b;
+
+ return e;
+}
+
+/* */
+
+struct QTheoraDecoderSetup {
+
+ MemoryPool_t Pool;
+
+ IdentifyHeader_t Id;
+
+ SetupHeader_t Setup;
+
+}; /* QTheoraDecoderSetup */
+
+/* */
+
+QTheoraDecoderSetup_t* QT_CreateDecoderSetup(void)
+{
+ QTheoraDecoderSetup_t* t = (QTheoraDecoderSetup_t*)malloc(sizeof(QTheoraDecoderSetup_t));
+ if (t == NULL) {
+ return NULL;
+ }
+
+ memset(t, 0, sizeof(QTheoraDecoderSetup_t));
+
+ QT_MemoryPool_Init(&(t->Pool));
+
+ return t;
+}
+
+void QT_ReleaseDecoderSetup(QTheoraDecoderSetup_t* setup)
+{
+ if (setup != NULL) {
+ QT_MemoryPool_Release(&(setup->Pool));
+
+ free(setup);
+ }
+}
+
+BOOL QT_SetupDecoderSetupLacing(
+ QTheoraDecoderSetup_t* setup,
+ const VOID* packet,
+ SIZE_T size)
+{
+ extern BOOL g_QT_Enable_X86;
+ extern BOOL g_QT_Enable_MMX;
+ extern BOOL g_QT_Enable_SSE2;
+
+ if (g_QT_Enable_SSE2 || g_QT_Enable_MMX) {
+ BitReader_MMX_t d;
+ QT_BitReader_MMX_Initialize(&d, packet, size);
+
+ if (!QT_SetupDecoderSetupLacing_MMX(
+ &(setup->Id),
+ &(setup->Setup),
+ &(setup->Pool),
+ &d)) {
+ return FALSE;
+ }
+
+ _mm_empty();
+
+ } else if (g_QT_Enable_X86) {
+ BitReader_X86_t d;
+ QT_BitReader_X86_Initialize(&d, packet, size);
+
+ if (!QT_SetupDecoderSetupLacing_X86(
+ &(setup->Id),
+ &(setup->Setup),
+ &(setup->Pool),
+ &d)) {
+ return FALSE;
+ }
+
+ } else {
+ BitReader_C_t d;
+ QT_BitReader_C_Initialize(&d, packet, size);
+
+ if (!QT_SetupDecoderSetupLacing_C(
+ &(setup->Id),
+ &(setup->Setup),
+ &(setup->Pool),
+ &d)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* */
+
--- /dev/null
+/* TheoraDecoder.h */
+/* 2009/06/26 */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+/* */
+
+BOOL QT_Initialize(void);
+
+BOOL QT_SetEnableX86(BOOL b);
+BOOL QT_SetEnableMMX(BOOL b);
+BOOL QT_SetEnableSSE2(BOOL b);
+
+/* */
+
+struct QTheoraDecoderSetup;
+
+typedef struct QTheoraDecoderSetup QTheoraDecoderSetup_t;
+
+QTheoraDecoderSetup_t* QT_CreateDecoderSetup(void);
+
+void QT_ReleaseDecoderSetup(QTheoraDecoderSetup_t* setup);
+
+BOOL QT_SetupDecoderSetupLacing(
+ QTheoraDecoderSetup_t* setup,
+ const VOID* packet,
+ SIZE_T size);
+
+/* */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
--- /dev/null
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QMatroska", "Lib\QMatroska\QMatroska.vcproj", "{B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TBenchEx", "Tests\TBenchEx\TBenchEx.vcproj", "{E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865} = {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF} = {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QTheoraEx", "Lib\QTheoraEx\QTheoraEx.vcproj", "{2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|Win32 = Debug|Win32
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}.Debug|Win32.Build.0 = Debug|Win32
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}.Release|Any CPU.ActiveCfg = Release|Win32
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}.Release|Win32.ActiveCfg = Release|Win32
+ {B108EB7F-BE91-4F76-AAAF-3E4EA95BBFFF}.Release|Win32.Build.0 = Release|Win32
+ {E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}.Debug|Win32.Build.0 = Debug|Win32
+ {E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}.Release|Any CPU.ActiveCfg = Release|Win32
+ {E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}.Release|Win32.ActiveCfg = Release|Win32
+ {E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}.Release|Win32.Build.0 = Release|Win32
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}.Debug|Win32.Build.0 = Debug|Win32
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}.Release|Any CPU.ActiveCfg = Release|Win32
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}.Release|Win32.ActiveCfg = Release|Win32
+ {2FE5C617-C9E8-48DD-BB21-CEC1DCD32865}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
--- /dev/null
+// Main.cpp
+// 2009/06/26
+
+#include "StdAfx.h"
+
+#include "Matroska.h"
+#include "TheoraDecoder.h"
+
+// #include "YUVReader.h"
+
+class TestApp {
+
+ QM_Reader_t* m_reader;
+
+ INT32 m_vid;
+
+ INT64 m_vd;
+
+// YUVReader* m_yuv;
+
+public:
+
+ TestApp() : m_reader(0), m_vid(0), m_vd(0)
+ {
+ }
+
+ ~TestApp()
+ {
+ QM_ReleaseReader(m_reader);
+ }
+
+ bool Setup(LPCWSTR mkv, LPCWSTR yuv)
+ {
+ m_reader = QM_CreateReader();
+ if (m_reader == 0) {
+ return false;
+ }
+
+ if (!QM_OpenReader(m_reader, mkv)) {
+ return false;
+ }
+
+ if (!CheckVideo()) {
+ return false;
+ }
+
+#if 0
+ if (m_vid != 0 && yuv != 0) {
+ m_yuv = new YUVReader();
+
+ if (!m_yuv->Open(yuv)) {
+ return false;
+ }
+ }
+#endif
+
+ return true;
+ }
+
+ bool Decode()
+ {
+ INT32 i = 0;
+
+ DWORD start = timeGetTime();
+
+ DWORD dtime = 0;
+
+ for (; ; ) {
+ QM_Block_t block;
+ INT32 code = QM_ReadBlock(
+ m_reader,
+ &block);
+ if (code < 0) {
+ return false;
+ }
+ if (code == 0) {
+ break;
+ }
+
+ if (block.TrackNo == m_vid) {
+ DWORD ds = timeGetTime();
+
+#if 0
+ QT_Output_t output = { 0 };
+ if (!QT_DecodeFrame(
+ m_vdecoder,
+ block.Payload,
+ block.Size,
+ &output)) {
+ return false;
+ }
+#endif
+
+ DWORD de = timeGetTime();
+
+ dtime += de - ds;
+
+ i++;
+
+#if 0
+ if (m_yuv != 0 && !Compare(&output)) {
+ printf("ERROR Compare : %d\n", i);
+ }
+#endif
+
+ }
+ }
+
+ DWORD end = timeGetTime();
+
+ if (i > 0) {
+ DWORD elapsed = end - start;
+
+ INT64 t = ((INT64)elapsed * 10) / i;
+
+ printf("Frames: %d\n", i);
+ printf("Time: %d ms / %d ms\n", elapsed, dtime);
+ printf("FTime: %d.%01d ms\n", (INT32)(t / 10), (INT32)(t % 10));
+
+ INT64 ft = ((INT64)elapsed * 1000*1000) / i;
+ DOUBLE fr = (DOUBLE)m_vd / ft;
+ printf("FRate: %lg\n", fr);
+ }
+
+ return true;
+ }
+
+private:
+
+#if 0
+ bool Compare(QT_Output_t* output)
+ {
+ if (!m_yuv->ReadFrame()) {
+ return false;
+ }
+
+ if (!m_yuv->Compare(output)) {
+ return false;
+ }
+
+ return true;
+ }
+#endif
+
+ bool CheckVideo()
+ {
+ const QM_Track_t* track = QM_GetTracks(m_reader);
+ const QM_Track_t* end = track + QM_GetTrackCount(m_reader);
+
+ for (; track < end; track++) {
+ if (strcmp(track->CodecId, "V_THEORA") == 0) {
+ TestSetup(track->CodecPrivate, track->CodecPrivateSize);
+
+#if 0
+ m_vsetup = QT_CreateDecoderSetup();
+ if (m_vsetup == 0) {
+ return false;
+ }
+
+ if (!QT_SetupDecoderSetupLacing(
+ m_vsetup,
+ track->CodecPrivate,
+ track->CodecPrivateSize)) {
+ return false;
+ }
+
+ m_vdecoder = QT_CreateDecoder();
+ if (m_vdecoder == 0) {
+ return false;
+ }
+
+ if (!QT_SetupDecoder(m_vdecoder, m_vsetup)) {
+ return false;
+ }
+#endif
+
+ m_vid = track->TrackNo;
+
+ m_vd = track->TrackDuration;
+
+ break;
+ }
+ }
+
+ if (m_vid == 0) {
+ puts("No Video");
+ }
+
+ return true;
+ }
+
+ void TestSetup(const VOID* packet, SIZE_T size)
+ {
+ QT_SetEnableX86(FALSE);
+ QT_SetEnableMMX(FALSE);
+ QT_SetEnableSSE2(FALSE);
+
+ {
+ QTheoraDecoderSetup_t* setup = QT_CreateDecoderSetup();
+ if (setup != 0) {
+ if (!QT_SetupDecoderSetupLacing(setup, packet, size)) {
+ puts("Error");
+ }
+ QT_ReleaseDecoderSetup(setup);
+ }
+ }
+
+ QT_SetEnableX86(TRUE);
+ QT_SetEnableMMX(FALSE);
+ QT_SetEnableSSE2(FALSE);
+
+ {
+ QTheoraDecoderSetup_t* setup = QT_CreateDecoderSetup();
+ if (setup != 0) {
+ if (!QT_SetupDecoderSetupLacing(setup, packet, size)) {
+ puts("Error");
+ }
+ QT_ReleaseDecoderSetup(setup);
+ }
+ }
+
+ QT_SetEnableX86(TRUE);
+ QT_SetEnableMMX(TRUE);
+ QT_SetEnableSSE2(FALSE);
+
+ {
+ QTheoraDecoderSetup_t* setup = QT_CreateDecoderSetup();
+ if (setup != 0) {
+ if (!QT_SetupDecoderSetupLacing(setup, packet, size)) {
+ puts("Error");
+ }
+ QT_ReleaseDecoderSetup(setup);
+ }
+ }
+ }
+
+};
+
+int wmain(int argc, wchar_t* argv[])
+{
+ if (!QT_Initialize()) {
+ return -1;
+ }
+
+ LPCWSTR mkv = 0;
+ LPCWSTR yuv = 0;
+
+ bool no_SSE2 = false;
+
+ for (INT32 i = 1; i < argc; i++) {
+ LPCWSTR a = argv[i];
+ if (wcscmp(a, L"-n") == 0) {
+ no_SSE2 = true;
+ continue;
+ }
+
+ if (mkv == 0) {
+ mkv = a;
+ } else if (yuv == 0) {
+ yuv = a;
+ }
+ }
+
+ if (mkv == 0) {
+ puts("TBenchEx [input mkv] (ref yuv)");
+ return -1;
+ }
+
+#if 0
+ if (no_SSE2) {
+ QT_SetEnableSSE2(FALSE);
+ }
+#endif
+
+ SetThreadAffinityMask(GetCurrentThread(), 1);
+
+ TestApp app;
+ if (!app.Setup(mkv, yuv)) {
+ return -1;
+ }
+
+ if (!app.Decode()) {
+ puts("NG.");
+ return -1;
+ }
+
+ puts("DONE.");
+
+ return 0;
+}
+
--- /dev/null
+/* StdAfx.cpp */
+/* 2009/05/18 */
+
+#include "StdAfx.h"
+
--- /dev/null
+/* StdAfx.h */
+/* 2009/05/18 */
+
+#pragma once
+
+#include <windows.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <io.h>
+#include <fcntl.h>
+
+#define _USE_MATH_DEFINES
+
+#include <math.h>
+
+#include <intrin.h>
+#include <mmintrin.h>
+#include <xmmintrin.h>
+#include <emmintrin.h>
+
+#include <mmsystem.h>
+#pragma comment(lib, "winmm.lib")
+
+#define ALIGN(X) _declspec(align(X))
+
--- /dev/null
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="TBenchEx"
+ ProjectGUID="{E6B2BDB3-A507-4C68-9E98-6A7DB1820B7F}"
+ RootNamespace="TBenchEx"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../Lib/QMatroska;../../Lib/QTheoraEx"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="../../Lib/QMatroska;../../Lib/QTheoraEx"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="\83\\81[\83X \83t\83@\83C\83\8b"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\Main.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\StdAfx.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="\83w\83b\83_\81[ \83t\83@\83C\83\8b"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\StdAfx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\YUVReader.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="\83\8a\83\\81[\83X \83t\83@\83C\83\8b"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
--- /dev/null
+// YUVReader.h
+// 2009/05/19
+
+#pragma once
+
+// YUVReader
+class YUVReader {
+
+ FILE* m_fp;
+
+ INT32 m_CX;
+ INT32 m_CY;
+
+ UINT8* m_Y;
+ UINT8* m_U;
+ UINT8* m_V;
+
+public:
+
+ YUVReader() : m_fp(0), m_CX(0), m_CY(0), m_Y(0), m_U(0), m_V(0)
+ {
+ }
+
+ ~YUVReader()
+ {
+ if (m_fp != 0 && m_fp != stdin) {
+ fclose(m_fp);
+ }
+
+ free(m_Y);
+ free(m_U);
+ free(m_V);
+ }
+
+ bool Open(LPCWSTR path)
+ {
+ FILE* fp = 0;
+
+ if (wcscmp(path, L"-") == 0) {
+ _setmode(
+ _fileno(stdin),
+ _O_BINARY);
+
+ fp = stdin;
+
+ } else {
+ _wfopen_s(&fp, path, L"rb");
+ if (fp == 0) {
+ return false;
+ }
+ }
+
+ m_fp = fp;
+
+ char buf[80+1]; buf[80] = '\0';
+ for (INT32 i = 0; i < 80; i++) {
+ INT32 ch = fgetc(m_fp);
+ if (ch == '\n' || ch == EOF) {
+ buf[i] = '\0';
+ break;
+ }
+ buf[i] = ch;
+ }
+
+ if (strncmp(buf, "YUV4MPEG2 ", 10) != 0) {
+ return false;
+ }
+
+ int cx = -1;
+ int cy = -1;
+ if (sscanf_s(buf + 10, "W%d H%d", &cx, &cy) != 2) {
+ return false;
+ }
+
+ if (cx <= 0 || cy <= 0) {
+ return false;
+ }
+
+ m_CX = cx;
+ m_CY = cy;
+
+ m_Y = (UINT8*)malloc(m_CX * m_CY );
+ m_U = (UINT8*)malloc(m_CX * m_CY / 4);
+ m_V = (UINT8*)malloc(m_CX * m_CY / 4);
+
+ if (m_Y == 0 || m_U == 0 || m_V == 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+ bool ReadFrame()
+ {
+ char buf[80+1]; buf[80] = '\0';
+ for (INT32 i = 0; i < 80; i++) {
+ INT32 ch = fgetc(m_fp);
+ if (ch == '\n' || ch == EOF) {
+ buf[i] = '\0';
+ break;
+ }
+ buf[i] = ch;
+ }
+
+ if (strncmp(buf, "FRAME", 5) != 0) {
+ return false;
+ }
+
+ fread(m_Y, m_CX * m_CY, 1, m_fp);
+ fread(m_U, m_CX * m_CY / 4, 1, m_fp);
+ fread(m_V, m_CX * m_CY / 4, 1, m_fp);
+
+ return true;
+ }
+
+ bool Compare(QT_Output_t* f)
+ {
+ INT32 x, y;
+
+ const UINT8* Y = f->Plane[0] + m_CX * (m_CY - 1);
+ const UINT8* U = f->Plane[1] + m_CX / 2 * (m_CY / 2 - 1);
+ const UINT8* V = f->Plane[2] + m_CX / 2 * (m_CY / 2 - 1);
+
+ const UINT8* R = m_Y;
+
+ for (y = 0; y < m_CY; y++, Y -= m_CX) {
+ const UINT8* T = Y;
+ for (x = 0; x < m_CX; x++, R++, T++) {
+ if (*R != *T) {
+ printf("Y: %d,%d : %02X -> %02X\n", x, y, *R, *T);
+
+ return false;
+ }
+ }
+ }
+
+ const UINT8* R0 = m_U;
+ const UINT8* R1 = m_V;
+
+ for (y = 0; y < m_CY / 2; y++, U -= m_CX / 2, V -= m_CX / 2) {
+ const UINT8* T0 = U;
+ const UINT8* T1 = V;
+ for (x = 0; x < m_CX / 2; x++, R0++, T0++, R1++, T1++) {
+ if (*R0 != *T0) {
+ printf("U: %d,%d : %02X -> %02X\n", x, y, *R0, *T0);
+
+ return false;
+ }
+
+ if (*R1 != *T1) {
+ printf("V: %d,%d : %02X -> %02X\n", x, y, *R1, *T1);
+
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+}; // YUVReader
+