summaryrefslogtreecommitdiffstats
path: root/Src/mp4v
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 14:54:57 +0200
committerJef <jef@targetspot.com>2024-09-24 14:54:57 +0200
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/mp4v
parentAdding .gitignore (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.bz2
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.lz
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.xz
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.zst
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.zip
Diffstat (limited to 'Src/mp4v')
-rw-r--r--Src/mp4v/MFTDecoder.cpp465
-rw-r--r--Src/mp4v/MFTDecoder.h25
-rw-r--r--Src/mp4v/api.h9
-rw-r--r--Src/mp4v/avi_mp4v_decoder.cpp135
-rw-r--r--Src/mp4v/avi_mp4v_decoder.h40
-rw-r--r--Src/mp4v/main.cpp87
-rw-r--r--Src/mp4v/mkv_mp4v_decoder.cpp163
-rw-r--r--Src/mp4v/mkv_mp4v_decoder.h41
-rw-r--r--Src/mp4v/mp4_mp4v_decoder.cpp103
-rw-r--r--Src/mp4v/mp4_mp4v_decoder.h31
-rw-r--r--Src/mp4v/mp4v.rc76
-rw-r--r--Src/mp4v/mp4v.sln41
-rw-r--r--Src/mp4v/mpeg4vid.vcxproj259
-rw-r--r--Src/mp4v/mpeg4vid.vcxproj.filters56
-rw-r--r--Src/mp4v/resource.h14
-rw-r--r--Src/mp4v/version.rc239
16 files changed, 1584 insertions, 0 deletions
diff --git a/Src/mp4v/MFTDecoder.cpp b/Src/mp4v/MFTDecoder.cpp
new file mode 100644
index 000000000..1a82cfd94
--- /dev/null
+++ b/Src/mp4v/MFTDecoder.cpp
@@ -0,0 +1,465 @@
+#include "MFTDecoder.h"
+#include <Mfapi.h>
+#include <wmcodecdsp.h>
+#include <Mferror.h>
+
+
+//-----------------------------------------------------------------------------
+// GetDefaultStride
+//
+// Gets the default stride for a video frame, assuming no extra padding bytes.
+//
+//-----------------------------------------------------------------------------
+
+static HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride)
+{
+ LONG lStride = 0;
+
+ // Try to get the default stride from the media type.
+ HRESULT hr = pType->GetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32*)&lStride);
+ if (FAILED(hr))
+ {
+ // Attribute not set. Try to calculate the default stride.
+ GUID subtype = GUID_NULL;
+
+ UINT32 width = 0;
+ UINT32 height = 0;
+
+ // Get the subtype and the image size.
+ hr = pType->GetGUID(MF_MT_SUBTYPE, &subtype);
+ if (SUCCEEDED(hr))
+ {
+ hr = MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &width, &height);
+ }
+ if (SUCCEEDED(hr))
+ {
+ hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, &lStride);
+ }
+
+ // Set the attribute for later reference.
+ if (SUCCEEDED(hr))
+ {
+ (void)pType->SetUINT32(MF_MT_DEFAULT_STRIDE, UINT32(lStride));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *plStride = lStride;
+ }
+ return hr;
+}
+
+
+static HRESULT ConfigureOutput(IMFTransform *decoder, LONG *stride)
+{
+ HRESULT hr = S_OK;
+ IMFMediaType *media_type = 0;
+ AM_MEDIA_TYPE *format = NULL;
+ int index=0;
+ while(SUCCEEDED(hr)) {
+ hr = decoder->GetOutputAvailableType(0, index++, &media_type);
+ if (FAILED(hr)) {
+ break;
+ }
+ media_type->GetRepresentation(FORMAT_MFVideoFormat, (LPVOID*)&format);
+ MFVIDEOFORMAT* z = (MFVIDEOFORMAT*)format->pbFormat;
+ unsigned int surface_format = z->surfaceInfo.Format;
+ media_type->FreeRepresentation(FORMAT_MFVideoFormat, (LPVOID)format);
+
+ if (surface_format == '21VY') { // MFVideoFormat_YV12
+ hr = GetDefaultStride(media_type, stride);
+ hr = decoder->SetOutputType(0, media_type, 0);
+ break;
+ }
+
+ }
+ if(media_type) {
+ media_type->Release();
+ }
+ return hr;
+}
+
+
+MFTDecoder::MFTDecoder()
+{
+ decoder = 0;
+ stride = 0;
+ width = 0;
+ height = 0;
+}
+
+MFTDecoder::~MFTDecoder()
+{
+ if (decoder) {
+ decoder->Release();
+ }
+}
+
+static HRESULT CreateInputMediaType(IMFMediaType **_media_type, VIDEOINFOHEADER *header)
+{
+ HRESULT hr=E_FAIL;
+ IMFMediaType *media_type=0;
+ do {
+ hr = MFCreateMediaType(&media_type);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = MFInitMediaTypeFromVideoInfoHeader(media_type, header, 88);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ if (FAILED(hr)) {
+ break;
+ }
+
+ *_media_type = media_type;
+ return S_OK;
+ } while(0);
+
+ if (media_type) {
+ media_type->Release();
+ }
+ return hr;
+}
+
+HRESULT MFTDecoder::Open(VIDEOINFOHEADER *header)
+{
+ HRESULT hr=E_FAIL;
+ hr = CoCreateInstance(CLSID_CMpeg4sDecMFT, NULL, CLSCTX_INPROC_SERVER, __uuidof(IMFTransform), (void**)&decoder);
+
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ /* set input */
+ IMFMediaType *media_type=0;
+ hr = CreateInputMediaType(&media_type, header);
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ hr = decoder->SetInputType(0, media_type, 0);
+ media_type->Release();
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ /* set output */
+
+ ConfigureOutput(decoder, &stride);
+ width=0;
+ height=0;
+
+ decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
+ decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
+
+ return S_OK;
+}
+
+HRESULT MFTDecoder::GetOutputFormat(UINT *width, UINT *height, bool *flip, double *aspect)
+{
+ HRESULT hr=E_FAIL;
+ IMFMediaType *media_type = 0;
+
+ do {
+ hr = decoder->GetOutputCurrentType(0, &media_type);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ if (width && height) {
+ hr = MFGetAttributeSize(media_type, MF_MT_FRAME_SIZE, width, height);
+ if (FAILED(hr)) {
+ break;
+ }
+ }
+
+ if (flip) {
+ LONG stride;
+ hr = GetDefaultStride(media_type, &stride);
+ if (FAILED(hr)) {
+ break;
+ }
+ *flip = stride<0;
+ }
+
+ if (aspect) {
+ MFRatio PAR = {0};
+ hr = MFGetAttributeRatio(media_type, MF_MT_PIXEL_ASPECT_RATIO,
+ (UINT32*)&PAR.Numerator,
+ (UINT32*)&PAR.Denominator);
+
+ if (FAILED(hr)) {
+ *aspect = 1.0;
+ } else {
+ *aspect = (double)PAR.Numerator / (double)PAR.Denominator;
+ }
+
+ }
+ } while(0);
+ if (media_type) {
+ media_type->Release();
+ }
+ return hr;
+}
+
+HRESULT MFTDecoder::Feed(const void *data, size_t data_size, uint64_t timestamp_hundred_nanos)
+{
+ HRESULT hr=E_FAIL;
+ IMFMediaBuffer *buffer = 0;
+ BYTE *buffer_pointer = 0;
+ IMFSample *sample = 0;
+
+ do {
+ hr = MFCreateMemoryBuffer((DWORD)data_size, &buffer);
+ if (FAILED(hr)) {
+ break;
+ }
+ hr = buffer->Lock(&buffer_pointer, NULL, NULL);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ memcpy(buffer_pointer, data, data_size);
+
+ hr = buffer->Unlock();
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = buffer->SetCurrentLength((DWORD)data_size);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = MFCreateSample(&sample);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = sample->AddBuffer(buffer);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = sample->SetSampleTime(timestamp_hundred_nanos);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = decoder->ProcessInput(0, sample, 0);
+ if (FAILED(hr)) {
+ break;
+ }
+ } while(0);
+ if (buffer) {
+ buffer->Release();
+ }
+
+ if (sample) {
+ sample->Release();
+ }
+ return hr;
+}
+
+static HRESULT CreateOutputSample(IMFTransform *decoder, IMFSample **_output_sample)
+{
+ HRESULT hr=E_FAIL;
+ MFT_OUTPUT_STREAM_INFO stream_info;
+ IMFMediaBuffer *media_buffer = 0;
+ IMFSample *sample = 0;
+
+ do {
+ hr = MFCreateSample(&sample);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = decoder->GetOutputStreamInfo(0, &stream_info);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = MFCreateAlignedMemoryBuffer(stream_info.cbSize, MF_16_BYTE_ALIGNMENT, &media_buffer);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = sample->AddBuffer(media_buffer);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ if (media_buffer) {
+ media_buffer->Release();
+ }
+ *_output_sample = sample;
+ return S_OK;
+ } while(0);
+ if (sample) {
+ sample->Release();
+ }
+
+ if (media_buffer) {
+ media_buffer->Release();
+ }
+ return hr;
+}
+
+// Release the events that an MFT might allocate in IMFTransform::ProcessOutput().
+static void ReleaseEventCollection(MFT_OUTPUT_DATA_BUFFER &pBuffers)
+{
+ if (pBuffers.pEvents) {
+ pBuffers.pEvents->Release();
+ pBuffers.pEvents = NULL;
+ }
+
+}
+HRESULT MFTDecoder::GetFrame(IMFMediaBuffer **out_buffer, uint64_t *hundrednanos)
+{
+ HRESULT hr=E_FAIL;
+ IMFSample *output_sample=0;
+ DWORD mftStatus;
+ do {
+ hr = CreateOutputSample(decoder, &output_sample);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ MFT_OUTPUT_DATA_BUFFER mftDataBuffer = {0, };
+ mftDataBuffer.pSample = output_sample;
+ mftStatus = 0;
+
+ hr = decoder->ProcessOutput(0, 1, &mftDataBuffer, &mftStatus);
+ if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
+ break;
+ }
+ if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
+ ConfigureOutput(decoder, &stride);
+ width=0;
+ height=0;
+ } else if (FAILED(hr)) {
+ break;
+ } else {
+ if (mftDataBuffer.pSample) {
+ IMFMediaBuffer *mediaBuffer;
+ hr = mftDataBuffer.pSample->GetBufferByIndex(0, &mediaBuffer);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ LONGLONG sample_time;
+ output_sample->GetSampleTime(&sample_time);
+ if (hundrednanos) {
+ *hundrednanos = sample_time;
+ }
+ *out_buffer = mediaBuffer;
+ }
+ ReleaseEventCollection(mftDataBuffer);
+ }
+ } while (0);
+
+ if (output_sample) {
+ output_sample->Release();
+ }
+
+ return hr;
+}
+
+HRESULT MFTDecoder::Flush()
+{
+ return decoder->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0);
+}
+
+HRESULT MFTDecoder::Drain()
+{
+ return decoder->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0);
+}
+
+HRESULT MFTDecoder::GetFrame(YV12_PLANES **data, void **decoder_data, uint64_t *mft_timestamp)
+{
+ HRESULT hr=E_FAIL;
+ IMFMediaBuffer *media_buffer = 0;
+ IMFMediaType *media_type = 0;
+ do {
+ if (!height || !stride) {
+ hr = decoder->GetOutputCurrentType(0, &media_type);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = MFGetAttributeSize(media_type, MF_MT_FRAME_SIZE, &width, &height);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ hr = GetDefaultStride(media_type, &stride);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ }
+ hr = this->GetFrame(&media_buffer, mft_timestamp);
+ if (FAILED(hr)) {
+ break;
+ }
+
+ YV12_PLANES *planes = (YV12_PLANES *)malloc(sizeof(YV12_PLANES));
+ IMF2DBuffer *buffer2d=0;
+ if (SUCCEEDED(media_buffer->QueryInterface(&buffer2d))) {
+ BYTE *pbScanline0;
+ LONG pitch;
+ buffer2d->Lock2D(&pbScanline0, &pitch);
+ planes->y.baseAddr = pbScanline0;
+ planes->y.rowBytes = pitch;
+ pbScanline0 += pitch * height;
+ planes->v.baseAddr = pbScanline0;
+ planes->v.rowBytes = pitch/2;
+ pbScanline0 += pitch * height/4;
+ planes->u.baseAddr = pbScanline0;
+ planes->u.rowBytes = pitch/2;
+ buffer2d->Release();
+ } else {
+ DWORD length, max_length;
+ BYTE *video_data;
+ media_buffer->Lock(&video_data, &length, &max_length);
+
+ planes->y.baseAddr = video_data;
+ planes->y.rowBytes = stride;
+ video_data += stride * height;
+ planes->v.baseAddr = video_data;
+ planes->v.rowBytes = stride/2;
+ video_data += (stride/2) * (height/2);
+ planes->u.baseAddr = video_data;
+ planes->u.rowBytes = stride/2;
+ }
+ *data = planes;
+ *decoder_data = media_buffer;
+ } while(0);
+
+ if (media_type) {
+ media_type->Release();
+ }
+
+ return hr;
+}
+
+HRESULT MFTDecoder::FreeFrame(YV12_PLANES *data, void *decoder_data)
+{
+ IMFMediaBuffer *buffer= (IMFMediaBuffer *)decoder_data;
+ if (buffer) {
+ IMF2DBuffer *buffer2d=0;
+ if (SUCCEEDED(buffer->QueryInterface(&buffer2d))) {
+ buffer2d->Unlock2D();
+ buffer2d->Release();
+ } else {
+ buffer->Unlock();
+ }
+ buffer->Release();
+ }
+ free(data);
+ return S_OK;
+} \ No newline at end of file
diff --git a/Src/mp4v/MFTDecoder.h b/Src/mp4v/MFTDecoder.h
new file mode 100644
index 000000000..997b24a9d
--- /dev/null
+++ b/Src/mp4v/MFTDecoder.h
@@ -0,0 +1,25 @@
+#pragma once
+#include <Mftransform.h>
+#include <bfc/platform/types.h>
+#include "../Winamp/wa_ipc.h"
+#include <Amvideo.h>
+
+class MFTDecoder
+{
+public:
+ MFTDecoder();
+ ~MFTDecoder();
+
+ HRESULT Open(VIDEOINFOHEADER *header);
+ HRESULT Feed(const void *data, size_t data_size, uint64_t timestamp_hundred_nanos);
+ HRESULT GetFrame(IMFMediaBuffer **output_buffer, uint64_t *hundrednanos);
+ HRESULT GetFrame(YV12_PLANES **data, void **decoder_data, uint64_t *mft_timestamp);
+ HRESULT FreeFrame(YV12_PLANES *data, void *decoder_data);
+ HRESULT GetOutputFormat(UINT *width, UINT *height, bool *flip, double *aspect);
+ HRESULT Flush();
+ HRESULT Drain();
+
+ IMFTransform *decoder;
+ LONG stride;
+ UINT32 width, height;
+}; \ No newline at end of file
diff --git a/Src/mp4v/api.h b/Src/mp4v/api.h
new file mode 100644
index 000000000..3ae0e226c
--- /dev/null
+++ b/Src/mp4v/api.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <api/service/api_service.h>
+extern api_service *serviceManager;
+#define WASABI_API_SVC serviceManager
+
+#include "../winamp/api_winamp.h"
+extern api_winamp *winampApi;
+#define AGAVE_API_WINAMP winampApi \ No newline at end of file
diff --git a/Src/mp4v/avi_mp4v_decoder.cpp b/Src/mp4v/avi_mp4v_decoder.cpp
new file mode 100644
index 000000000..185cb84ca
--- /dev/null
+++ b/Src/mp4v/avi_mp4v_decoder.cpp
@@ -0,0 +1,135 @@
+#include "avi_mp4v_decoder.h"
+#include "../Winamp/wa_ipc.h"
+#include "../nsavi/read.h"
+#include <mmsystem.h>
+#include <Amvideo.h>
+#include <Dvdmedia.h>
+
+int AVIDecoderCreator::CreateVideoDecoder(const nsavi::AVIH *avi_header, const nsavi::STRH *stream_header, const nsavi::STRF *stream_format, const nsavi::STRD *stream_data, ifc_avivideodecoder **decoder)
+{
+ nsavi::video_format *format = (nsavi::video_format *)stream_format;
+ if (format) {
+ if (
+ format->compression == 'DIVX' || format->compression == 'divx' // xvid
+ || format->compression == 'xvid' || format->compression == 'XVID' // divx
+ || format->compression == 'v4pm' // mp4v
+ || format->compression == '05XD' // divx 5
+ || format->compression == nsaviFOURCC('S','E','D','G') // dunno what this is exactly
+ /* || format->compression == '3VID' // divx 3, let's hope it plays */
+ ) {
+ VIDEOINFOHEADER header = {0, };
+ //header.rcSource.right = format->width;
+ //header.rcSource.bottom = format->height;
+ //header.rcTarget = header.rcSource;
+ memcpy(&header.bmiHeader, &format->video_format_size_bytes, 40);
+
+ MFTDecoder *ctx = new MFTDecoder;
+ if (!ctx) {
+ return CREATEDECODER_FAILURE;
+ }
+ if (FAILED(ctx->Open(&header))) {
+ delete ctx;
+ return CREATEDECODER_FAILURE;
+ }
+ *decoder = new AVIMP4V(ctx, stream_header, format);
+ return CREATEDECODER_SUCCESS;
+ }
+ }
+
+ return CREATEDECODER_NOT_MINE;
+}
+
+
+#define CBCLASS AVIDecoderCreator
+START_DISPATCH;
+CB(CREATE_VIDEO_DECODER, CreateVideoDecoder)
+END_DISPATCH;
+#undef CBCLASS
+
+AVIMP4V::AVIMP4V(MFTDecoder *decoder, const nsavi::STRH *stream_header, const nsavi::video_format *stream_format)
+: decoder(decoder), stream_header(stream_header), stream_format(stream_format)
+{
+ if (stream_format->size_bytes > 40) {
+ //MPEG4Video_DecodeFrame(decoder, ((const uint8_t *)stream_format) + 44, stream_format->size_bytes - stream_format->video_format_size_bytes, 0);
+ }
+}
+
+AVIMP4V::~AVIMP4V()
+{
+ delete decoder;
+}
+
+int AVIMP4V::GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio, int *flip)
+{
+ UINT width, height;
+ bool local_flip=false;
+ if (SUCCEEDED(decoder->GetOutputFormat(&width, &height, &local_flip, aspect_ratio))) {
+ *x = width;
+ *y = height;
+ *color_format = '21VY';
+ *flip = local_flip;
+ return AVI_SUCCESS;
+ }
+ return AVI_FAILURE;
+}
+
+int AVIMP4V::DecodeChunk(uint16_t type, const void *inputBuffer, size_t inputBufferBytes)
+{
+ if (decoder) {
+ decoder->Feed(inputBuffer, inputBufferBytes, 0);
+ return AVI_SUCCESS;
+ }
+
+ return AVI_FAILURE;
+}
+
+void AVIMP4V::Flush()
+{
+ if (decoder) {
+ decoder->Flush();
+ }
+}
+
+int AVIMP4V::GetPicture(void **data, void **decoder_data)
+{
+ if (SUCCEEDED(decoder->GetFrame((YV12_PLANES **)data, decoder_data, 0))) {
+ return AVI_SUCCESS;
+ } else {
+ return AVI_FAILURE;
+ }
+}
+
+void AVIMP4V::FreePicture(void *data, void *decoder_data)
+{
+ decoder->FreeFrame((YV12_PLANES *)data, decoder_data);
+}
+
+void AVIMP4V::EndOfStream()
+{
+ decoder->Drain();
+}
+
+void AVIMP4V::HurryUp(int state)
+{
+ //if (decoder)
+ //MPEG4Video_HurryUp(decoder, state);
+}
+
+void AVIMP4V::Close()
+{
+ delete this;
+}
+
+#define CBCLASS AVIMP4V
+START_DISPATCH;
+CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
+CB(DECODE_CHUNK, DecodeChunk)
+VCB(FLUSH, Flush)
+CB(GET_PICTURE, GetPicture)
+VCB(FREE_PICTURE, FreePicture)
+VCB(END_OF_STREAM, EndOfStream)
+VCB(HURRY_UP, HurryUp)
+VCB(CLOSE, Close)
+END_DISPATCH;
+#undef CBCLASS
+
diff --git a/Src/mp4v/avi_mp4v_decoder.h b/Src/mp4v/avi_mp4v_decoder.h
new file mode 100644
index 000000000..ff65f6312
--- /dev/null
+++ b/Src/mp4v/avi_mp4v_decoder.h
@@ -0,0 +1,40 @@
+#pragma once
+#include "../Plugins/Input/in_avi/ifc_avivideodecoder.h"
+#include "../Plugins/Input/in_avi/svc_avidecoder.h"
+#include "MFTDecoder.h"
+
+// {3E450454-0286-4ad8-811F-60A49C933E9B}
+static const GUID avi_mp4v_guid =
+{ 0x3e450454, 0x286, 0x4ad8, { 0x81, 0x1f, 0x60, 0xa4, 0x9c, 0x93, 0x3e, 0x9b } };
+
+class AVIDecoderCreator : public svc_avidecoder
+{
+public:
+ static const char *getServiceName() { return "MPEG-4 Part 2 AVI Decoder"; }
+ static GUID getServiceGuid() { return avi_mp4v_guid; }
+ int CreateVideoDecoder(const nsavi::AVIH *avi_header, const nsavi::STRH *stream_header, const nsavi::STRF *stream_format, const nsavi::STRD *stream_data, ifc_avivideodecoder **decoder);
+protected:
+ RECVS_DISPATCH;
+};
+
+class AVIMP4V : public ifc_avivideodecoder
+{
+public:
+ AVIMP4V(MFTDecoder *decoder, const nsavi::STRH *stream_header, const nsavi::video_format *stream_format);
+ ~AVIMP4V();
+
+ int GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio, int *flip);
+ int DecodeChunk(uint16_t type, const void *inputBuffer, size_t inputBufferBytes);
+ void Flush();
+ int GetPicture(void **data, void **decoder_data);
+ void FreePicture(void *data, void *decoder_data);
+ void EndOfStream();
+ void HurryUp(int state);
+ void Close();
+private:
+ MFTDecoder *decoder;
+ const nsavi::STRH *stream_header;
+ const nsavi::video_format *stream_format;
+protected:
+ RECVS_DISPATCH;
+}; \ No newline at end of file
diff --git a/Src/mp4v/main.cpp b/Src/mp4v/main.cpp
new file mode 100644
index 000000000..ff7f1fe6d
--- /dev/null
+++ b/Src/mp4v/main.cpp
@@ -0,0 +1,87 @@
+#define WIN32_LEAN_AND_MEAN
+#include "api.h"
+#include <bfc/platform/export.h>
+#include "../Agave/Component/ifc_wa5component.h"
+#include "../nu/Singleton.h"
+#include "../nu/factoryt.h"
+#include "mp4_mp4v_decoder.h"
+#include "mkv_mp4v_decoder.h"
+#include "avi_mp4v_decoder.h"
+
+#define MF_INIT_GUIDS
+#include <Mfapi.h>
+#include <Mftransform.h>
+#include <wmcodecdsp.h>
+
+api_winamp *AGAVE_API_WINAMP=0;
+api_service *WASABI_API_SVC = 0;
+
+class MP4VComponent : public ifc_wa5component
+{
+public:
+ void RegisterServices(api_service *service);
+ void DeregisterServices(api_service *service);
+protected:
+ RECVS_DISPATCH;
+};
+
+template <class api_T>
+void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
+{
+ if (WASABI_API_SVC)
+ {
+ waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);
+ if (factory)
+ api_t = reinterpret_cast<api_T *>( factory->getInterface() );
+ }
+}
+
+template <class api_T>
+void ServiceRelease(api_T *api_t, GUID factoryGUID_t)
+{
+ if (WASABI_API_SVC)
+ {
+ waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);
+ if (factory)
+ factory->releaseInterface(api_t);
+ }
+ api_t = NULL;
+}
+
+static ServiceFactoryT<MP4VideoDecoder, MP4VMP4Decoder> mp4Factory;
+static MKVDecoderCreator mkvCreator;
+static SingletonServiceFactory<svc_mkvdecoder, MKVDecoderCreator> mkvFactory;
+static AVIDecoderCreator aviCreator;
+static SingletonServiceFactory<svc_avidecoder, AVIDecoderCreator> aviFactory;
+
+void MP4VComponent::RegisterServices(api_service *service)
+{
+ WASABI_API_SVC = service;
+ ServiceBuild(AGAVE_API_WINAMP, winampApiGuid);
+ if (!AGAVE_API_WINAMP || AGAVE_API_WINAMP->GetRegVer() >= 1)
+ {
+ mp4Factory.Register(WASABI_API_SVC);
+ mkvFactory.Register(WASABI_API_SVC, &mkvCreator);
+ aviFactory.Register(WASABI_API_SVC, &aviCreator);
+ }
+}
+
+void MP4VComponent::DeregisterServices(api_service *service)
+{
+ mp4Factory.Deregister(WASABI_API_SVC);
+ mkvFactory.Deregister(WASABI_API_SVC);
+ aviFactory.Deregister(WASABI_API_SVC);
+}
+
+static MP4VComponent component;
+extern "C" DLLEXPORT ifc_wa5component *GetWinamp5SystemComponent()
+{
+ return &component;
+}
+
+#define CBCLASS MP4VComponent
+START_DISPATCH;
+VCB(API_WA5COMPONENT_REGISTERSERVICES, RegisterServices)
+VCB(API_WA5COMPONENT_DEREEGISTERSERVICES, DeregisterServices)
+END_DISPATCH;
+#undef CBCLASS
diff --git a/Src/mp4v/mkv_mp4v_decoder.cpp b/Src/mp4v/mkv_mp4v_decoder.cpp
new file mode 100644
index 000000000..eedd7e887
--- /dev/null
+++ b/Src/mp4v/mkv_mp4v_decoder.cpp
@@ -0,0 +1,163 @@
+#include "mkv_mp4v_decoder.h"
+#include "../Winamp/wa_ipc.h" // for YV12_PLANES
+#include <mmsystem.h>
+#include <assert.h>
+
+int MKVDecoderCreator::CreateVideoDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::VideoData *video_data, ifc_mkvvideodecoder **decoder)
+{
+ if (!strcmp(codec_id, "V_MPEG4/ISO/ASP")
+ || !strcmp(codec_id, "V_MPEG4/ISO/SP"))
+ {
+ VIDEOINFOHEADER header = {0, };
+
+ header.bmiHeader.biHeight = (LONG)video_data->pixel_height;
+ header.bmiHeader.biWidth = (LONG)video_data->pixel_width;
+ header.bmiHeader.biCompression = 'v4pm';
+
+ MFTDecoder *ctx = new MFTDecoder;
+ if (!ctx) {
+ return CREATEDECODER_FAILURE;
+ }
+ HRESULT hr = ctx->Open(&header);
+ if (FAILED(hr)) {
+ delete ctx;
+ return CREATEDECODER_FAILURE;
+ }
+
+ if (ctx)
+ {
+ if (track_entry_data->codec_private && track_entry_data->codec_private_len) {
+ // mkv stores headers up to first VOP in codec_private
+ hr = ctx->Feed(track_entry_data->codec_private, track_entry_data->codec_private_len, 0);
+ if (FAILED(hr)) {
+ delete ctx;
+ return CREATEDECODER_FAILURE;
+ }
+ }
+ *decoder = new MKVMP4V(ctx, video_data);
+ return CREATEDECODER_SUCCESS;
+ }
+ else
+ {
+ return CREATEDECODER_FAILURE;
+ }
+ }
+ else if (!strcmp(codec_id, "V_MS/VFW/FOURCC"))
+ {
+ if (track_entry_data->codec_private && track_entry_data->codec_private_len)
+ {
+ const BITMAPINFOHEADER *header = (const BITMAPINFOHEADER *)track_entry_data->codec_private;
+ if (header->biCompression == 'DIVX'
+ || header->biCompression == '05XD')
+ {
+ if (track_entry_data->codec_private_len < 40) {
+ return CREATEDECODER_FAILURE;
+ }
+
+ VIDEOINFOHEADER video_header = {0, };
+ memcpy(&video_header.bmiHeader, header, 40);
+ assert(track_entry_data->codec_private_len == 40);
+
+ MFTDecoder *ctx = new MFTDecoder;
+ if (!ctx) {
+ return CREATEDECODER_FAILURE;
+ }
+ if (FAILED(ctx->Open(&video_header))) {
+ delete ctx;
+ return CREATEDECODER_FAILURE;
+ }
+
+ *decoder = new MKVMP4V(ctx, video_data);
+ return CREATEDECODER_SUCCESS;
+ }
+ }
+ return CREATEDECODER_NOT_MINE;
+ }
+ else
+ {
+ return CREATEDECODER_NOT_MINE;
+ }
+}
+
+
+#define CBCLASS MKVDecoderCreator
+START_DISPATCH;
+CB(CREATE_VIDEO_DECODER, CreateVideoDecoder)
+END_DISPATCH;
+#undef CBCLASS
+
+MKVMP4V::MKVMP4V(MFTDecoder *decoder, const nsmkv::VideoData *video_data) : decoder(decoder), video_data(video_data)
+{
+
+}
+
+MKVMP4V::~MKVMP4V()
+{
+ delete decoder;
+}
+
+int MKVMP4V::GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio)
+{
+ UINT width, height;
+ bool local_flip=false;
+ if (SUCCEEDED(decoder->GetOutputFormat(&width, &height, &local_flip, aspect_ratio))) {
+ *x = width;
+ *y = height;
+ *color_format = '21VY';
+ return MKV_SUCCESS;
+ }
+ return MKV_FAILURE;
+}
+
+int MKVMP4V::DecodeBlock(const void *inputBuffer, size_t inputBufferBytes, uint64_t timestamp)
+{
+ HRESULT hr;
+ hr=decoder->Feed(inputBuffer, inputBufferBytes, timestamp);
+ return MKV_SUCCESS;
+}
+
+void MKVMP4V::Flush()
+{
+ if (decoder) {
+ decoder->Flush();
+ }
+}
+
+int MKVMP4V::GetPicture(void **data, void **decoder_data, uint64_t *timestamp)
+{
+ if (SUCCEEDED(decoder->GetFrame((YV12_PLANES **)data, decoder_data, timestamp))) {
+ return MKV_SUCCESS;
+ } else {
+ return MKV_FAILURE;
+ }
+}
+
+void MKVMP4V::FreePicture(void *data, void *decoder_data)
+{
+ if (decoder) {
+ decoder->FreeFrame((YV12_PLANES *)data, decoder_data);
+ }
+}
+
+void MKVMP4V::HurryUp(int state)
+{
+// if (decoder)
+// MPEG4Video_HurryUp(decoder, state);
+}
+
+void MKVMP4V::Close()
+{
+ delete this;
+}
+
+#define CBCLASS MKVMP4V
+START_DISPATCH;
+CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
+CB(DECODE_BLOCK, DecodeBlock)
+VCB(FLUSH, Flush)
+CB(GET_PICTURE, GetPicture)
+VCB(FREE_PICTURE, FreePicture)
+VCB(HURRY_UP, HurryUp)
+VCB(CLOSE, Close)
+END_DISPATCH;
+#undef CBCLASS
diff --git a/Src/mp4v/mkv_mp4v_decoder.h b/Src/mp4v/mkv_mp4v_decoder.h
new file mode 100644
index 000000000..6027af0b3
--- /dev/null
+++ b/Src/mp4v/mkv_mp4v_decoder.h
@@ -0,0 +1,41 @@
+#pragma once
+#include "../Plugins/Input/in_mkv/ifc_mkvvideodecoder.h"
+#include "../Plugins/Input/in_mkv/svc_mkvdecoder.h"
+#include "MFTDecoder.h"
+
+// {E63A1285-DD51-4b2d-9847-F1C2A5638951}
+static const GUID mkv_mp4v_guid =
+{ 0xe63a1285, 0xdd51, 0x4b2d, { 0x98, 0x47, 0xf1, 0xc2, 0xa5, 0x63, 0x89, 0x51 } };
+
+
+class MKVDecoderCreator : public svc_mkvdecoder
+{
+public:
+ static const char *getServiceName() { return "MPEG-4 Part 2 MKV Decoder"; }
+ static GUID getServiceGuid() { return mkv_mp4v_guid; }
+ int CreateVideoDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::VideoData *video_data, ifc_mkvvideodecoder **decoder);
+protected:
+ RECVS_DISPATCH;
+};
+
+
+class MKVMP4V : public ifc_mkvvideodecoder
+{
+public:
+ MKVMP4V(MFTDecoder *decoder, const nsmkv::VideoData *video_data);
+~MKVMP4V();
+
+ int GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio);
+ int DecodeBlock(const void *inputBuffer, size_t inputBufferBytes, uint64_t timestamp);
+ void Flush();
+ int GetPicture(void **data, void **decoder_data, uint64_t *timestamp);
+ void FreePicture(void *data, void *decoder_data);
+ void HurryUp(int state);
+ void Close();
+private:
+ MFTDecoder *decoder;
+ const nsmkv::VideoData *video_data;
+
+protected:
+ RECVS_DISPATCH;
+}; \ No newline at end of file
diff --git a/Src/mp4v/mp4_mp4v_decoder.cpp b/Src/mp4v/mp4_mp4v_decoder.cpp
new file mode 100644
index 000000000..9f96a3412
--- /dev/null
+++ b/Src/mp4v/mp4_mp4v_decoder.cpp
@@ -0,0 +1,103 @@
+#include "mp4_mp4v_decoder.h"
+#include "../winamp/wa_ipc.h"
+
+
+MP4VMP4Decoder::MP4VMP4Decoder()
+{
+
+}
+
+MP4VMP4Decoder::~MP4VMP4Decoder()
+{
+
+}
+
+int MP4VMP4Decoder::Open(MP4FileHandle mp4_file, MP4TrackId mp4_track)
+{
+ HRESULT hr;
+ VIDEOINFOHEADER header = {0, };
+
+ header.bmiHeader.biHeight = MP4GetTrackVideoHeight(mp4_file, mp4_track);
+ header.bmiHeader.biWidth = MP4GetTrackVideoWidth(mp4_file, mp4_track);
+ header.bmiHeader.biCompression = 'v4pm';
+
+ hr = decoder.Open(&header);
+ if (FAILED(hr)) {
+ return MP4_VIDEO_FAILURE;
+ }
+
+ uint8_t *buffer = 0;
+ uint32_t buffer_size = 0;
+
+ if (MP4GetTrackESConfiguration(mp4_file, mp4_track, &buffer, &buffer_size)
+ && buffer && buffer_size) {
+ hr = decoder.Feed(buffer, buffer_size, 0);
+ MP4Free(buffer);
+ if (FAILED(hr)) {
+ return MP4_VIDEO_FAILURE;
+ }
+ }
+
+ return MP4_VIDEO_SUCCESS;
+}
+
+int MP4VMP4Decoder::GetOutputFormat(int *x, int *y, int *color_format, double *aspect_ratio)
+{
+ UINT width, height;
+ bool local_flip=false;
+ if (SUCCEEDED(decoder.GetOutputFormat(&width, &height, &local_flip, aspect_ratio))) {
+ *x = width;
+ *y = height;
+ *color_format = '21VY';
+ return MP4_VIDEO_SUCCESS;
+ }
+ return MP4_VIDEO_FAILURE;
+}
+
+int MP4VMP4Decoder::DecodeSample(const void *inputBuffer, size_t inputBufferBytes, MP4Timestamp timestamp)
+{
+ HRESULT hr;
+ hr=decoder.Feed(inputBuffer, inputBufferBytes, timestamp);
+ return MP4_VIDEO_SUCCESS;
+}
+
+int MP4VMP4Decoder::CanHandleCodec(const char *codecName)
+{
+ return !strcmp(codecName, "mp4v");
+}
+
+void MP4VMP4Decoder::Flush()
+{
+ decoder.Flush();
+}
+
+int MP4VMP4Decoder::GetPicture(void **data, void **decoder_data, MP4Timestamp *timestamp)
+{
+ if (SUCCEEDED(decoder.GetFrame((YV12_PLANES **)data, decoder_data, timestamp))) {
+ return MP4_VIDEO_SUCCESS;
+ } else {
+ return MP4_VIDEO_FAILURE;
+ }
+}
+
+void MP4VMP4Decoder::FreePicture(void *data, void *decoder_data)
+{
+ decoder.FreeFrame((YV12_PLANES *)data, decoder_data);
+}
+
+void MP4VMP4Decoder::Close()
+{
+}
+
+#define CBCLASS MP4VMP4Decoder
+START_DISPATCH;
+CB(MPEG4_VIDEO_OPEN, Open)
+CB(MPEG4_VIDEO_GETOUTPUTFORMAT, GetOutputFormat)
+CB(MPEG4_VIDEO_DECODE, DecodeSample)
+CB(MPEG4_VIDEO_HANDLES_CODEC, CanHandleCodec)
+VCB(MPEG4_VIDEO_FLUSH, Flush)
+CB(MPEG4_VIDEO_GET_PICTURE, GetPicture)
+VCB(MPEG4_VIDEO_FREE_PICTURE, FreePicture)
+VCB(MPEG4_VIDEO_CLOSE, Close)
+END_DISPATCH;
+#undef CBCLASS
diff --git a/Src/mp4v/mp4_mp4v_decoder.h b/Src/mp4v/mp4_mp4v_decoder.h
new file mode 100644
index 000000000..564cd736b
--- /dev/null
+++ b/Src/mp4v/mp4_mp4v_decoder.h
@@ -0,0 +1,31 @@
+#pragma once
+#include "../Plugins/Input/in_mp4/mpeg4video.h"
+#include "MFTDecoder.h"
+
+// {D3D14DCB-6AA8-4f59-A862-AA81D5AEE550}
+static const GUID mp4_mp4v_guid =
+{ 0xd3d14dcb, 0x6aa8, 0x4f59, { 0xa8, 0x62, 0xaa, 0x81, 0xd5, 0xae, 0xe5, 0x50 } };
+
+class MP4VMP4Decoder : public MP4VideoDecoder
+{
+public:
+ static const char *getServiceName() { return "MPEG-4 Part 2 MP4 Decoder"; }
+ static GUID getServiceGuid() { return mp4_mp4v_guid; }
+ MP4VMP4Decoder();
+ ~MP4VMP4Decoder();
+
+private:
+ /* mpeg4video interface */
+ int Open(MP4FileHandle mp4_file, MP4TrackId mp4_track);
+ int GetOutputFormat(int *x, int *y, int *color_format, double *aspect_ratio);
+ int DecodeSample(const void *inputBuffer, size_t inputBufferBytes, MP4Timestamp timestamp);
+ void Flush();
+ void Close();
+ int CanHandleCodec(const char *codecName);
+ int GetPicture(void **data, void **decoder_data, MP4Timestamp *timestamp);
+ void FreePicture(void *data, void *decoder_data);
+
+ MFTDecoder decoder;
+protected:
+ RECVS_DISPATCH;
+}; \ No newline at end of file
diff --git a/Src/mp4v/mp4v.rc b/Src/mp4v/mp4v.rc
new file mode 100644
index 000000000..fcff77115
--- /dev/null
+++ b/Src/mp4v/mp4v.rc
@@ -0,0 +1,76 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.K.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#include ""version.rc2""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.K.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc2"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/mp4v/mp4v.sln b/Src/mp4v/mp4v.sln
new file mode 100644
index 000000000..e8f593b1e
--- /dev/null
+++ b/Src/mp4v/mp4v.sln
@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29424.173
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mp4v", "mpeg4vid.vcxproj", "{B0DE4AD5-556B-4FF5-9DA5-23DE901556DD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmp4v2", "..\libmp4v2\libmp4v2.vcxproj", "{EFB9B882-6A8B-463D-A8E3-A2807AFC5D9F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B0DE4AD5-556B-4FF5-9DA5-23DE901556DD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B0DE4AD5-556B-4FF5-9DA5-23DE901556DD}.Debug|Win32.Build.0 = Debug|Win32
+ {B0DE4AD5-556B-4FF5-9DA5-23DE901556DD}.Debug|x64.ActiveCfg = Debug|x64
+ {B0DE4AD5-556B-4FF5-9DA5-23DE901556DD}.Debug|x64.Build.0 = Debug|x64
+ {B0DE4AD5-556B-4FF5-9DA5-23DE901556DD}.Release|Win32.ActiveCfg = Release|Win32
+ {B0DE4AD5-556B-4FF5-9DA5-23DE901556DD}.Release|Win32.Build.0 = Release|Win32
+ {B0DE4AD5-556B-4FF5-9DA5-23DE901556DD}.Release|x64.ActiveCfg = Release|x64
+ {B0DE4AD5-556B-4FF5-9DA5-23DE901556DD}.Release|x64.Build.0 = Release|x64
+ {EFB9B882-6A8B-463D-A8E3-A2807AFC5D9F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {EFB9B882-6A8B-463D-A8E3-A2807AFC5D9F}.Debug|Win32.Build.0 = Debug|Win32
+ {EFB9B882-6A8B-463D-A8E3-A2807AFC5D9F}.Debug|x64.ActiveCfg = Debug|x64
+ {EFB9B882-6A8B-463D-A8E3-A2807AFC5D9F}.Debug|x64.Build.0 = Debug|x64
+ {EFB9B882-6A8B-463D-A8E3-A2807AFC5D9F}.Release|Win32.ActiveCfg = Release|Win32
+ {EFB9B882-6A8B-463D-A8E3-A2807AFC5D9F}.Release|Win32.Build.0 = Release|Win32
+ {EFB9B882-6A8B-463D-A8E3-A2807AFC5D9F}.Release|x64.ActiveCfg = Release|x64
+ {EFB9B882-6A8B-463D-A8E3-A2807AFC5D9F}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {560377AD-D785-4A38-AEBD-525E8969F62E}
+ EndGlobalSection
+EndGlobal
diff --git a/Src/mp4v/mpeg4vid.vcxproj b/Src/mp4v/mpeg4vid.vcxproj
new file mode 100644
index 000000000..bb899fb81
--- /dev/null
+++ b/Src/mp4v/mpeg4vid.vcxproj
@@ -0,0 +1,259 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>mp4v</ProjectName>
+ <ProjectGuid>{B0DE4AD5-556B-4FF5-9DA5-23DE901556DD}</ProjectGuid>
+ <RootNamespace>mpeg4vid</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../Wasabi;../libmp4v2;../libmp4v2/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MPEG4VID_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;Mfplat.lib;wmcodecdspuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../Wasabi;../libmp4v2;../libmp4v2/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;MPEG4VID_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;Mfplat.lib;wmcodecdspuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../Wasabi;../libmp4v2;../libmp4v2/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MPEG4VID_EXPORTS;;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;Mfplat.lib;wmcodecdspuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <DelayLoadDLLs>libmp4v2.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(ProjectDir)x86_Release\$(ProjectName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../Wasabi;../libmp4v2;../libmp4v2/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;MPEG4VID_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;Mfplat.lib;wmcodecdspuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <DelayLoadDLLs>libmp4v2.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(ProjectDir)x64_Release\$(ProjectName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\external_dependencies\libmp4v2\libmp4v2.vcxproj">
+ <Project>{efb9b882-6a8b-463d-a8e3-a2807afc5d9f}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\Wasabi\Wasabi.vcxproj">
+ <Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="avi_mp4v_decoder.cpp" />
+ <ClCompile Include="main.cpp" />
+ <ClCompile Include="MFTDecoder.cpp" />
+ <ClCompile Include="mkv_mp4v_decoder.cpp" />
+ <ClCompile Include="mp4_mp4v_decoder.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="api.h" />
+ <ClInclude Include="avi_mp4v_decoder.h" />
+ <ClInclude Include="MFTDecoder.h" />
+ <ClInclude Include="mkv_mp4v_decoder.h" />
+ <ClInclude Include="mp4_mp4v_decoder.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="mp4v.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Src/mp4v/mpeg4vid.vcxproj.filters b/Src/mp4v/mpeg4vid.vcxproj.filters
new file mode 100644
index 000000000..99a22f448
--- /dev/null
+++ b/Src/mp4v/mpeg4vid.vcxproj.filters
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="avi_mp4v_decoder.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="MFTDecoder.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mkv_mp4v_decoder.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mp4_mp4v_decoder.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="api.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="avi_mp4v_decoder.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="MFTDecoder.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mkv_mp4v_decoder.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mp4_mp4v_decoder.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{b9edfb5d-7bc8-4124-b4e7-9f8a8ef17933}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Ressource Files">
+ <UniqueIdentifier>{7c1b9074-c73f-4df0-8628-17cdb690ad39}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{a28cbe81-d9aa-43d7-8877-35010af5e0d4}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="mp4v.rc">
+ <Filter>Ressource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Src/mp4v/resource.h b/Src/mp4v/resource.h
new file mode 100644
index 000000000..f753272ad
--- /dev/null
+++ b/Src/mp4v/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by mp4v.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Src/mp4v/version.rc2 b/Src/mp4v/version.rc2
new file mode 100644
index 000000000..912e8661f
--- /dev/null
+++ b/Src/mp4v/version.rc2
@@ -0,0 +1,39 @@
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+#include "../Winamp/buildType.h"
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION WINAMP_PRODUCTVER
+ PRODUCTVERSION WINAMP_PRODUCTVER
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Winamp SA"
+ VALUE "FileDescription", "Winamp 5.x System Component"
+ VALUE "FileVersion", STR_WINAMP_PRODUCTVER
+ VALUE "InternalName", "mp4v.w5s"
+ VALUE "LegalCopyright", "Copyright © 2015-2023 Ben Allison"
+ VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
+ VALUE "OriginalFilename", "mp4v.w5s"
+ VALUE "ProductName", "Winamp MPEG-4 Part 2 Decoder Service"
+ VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END