diff options
Diffstat (limited to 'Src/mp4v')
-rw-r--r-- | Src/mp4v/MFTDecoder.cpp | 465 | ||||
-rw-r--r-- | Src/mp4v/MFTDecoder.h | 25 | ||||
-rw-r--r-- | Src/mp4v/api.h | 9 | ||||
-rw-r--r-- | Src/mp4v/avi_mp4v_decoder.cpp | 135 | ||||
-rw-r--r-- | Src/mp4v/avi_mp4v_decoder.h | 40 | ||||
-rw-r--r-- | Src/mp4v/main.cpp | 87 | ||||
-rw-r--r-- | Src/mp4v/mkv_mp4v_decoder.cpp | 163 | ||||
-rw-r--r-- | Src/mp4v/mkv_mp4v_decoder.h | 41 | ||||
-rw-r--r-- | Src/mp4v/mp4_mp4v_decoder.cpp | 103 | ||||
-rw-r--r-- | Src/mp4v/mp4_mp4v_decoder.h | 31 | ||||
-rw-r--r-- | Src/mp4v/mp4v.rc | 76 | ||||
-rw-r--r-- | Src/mp4v/mp4v.sln | 41 | ||||
-rw-r--r-- | Src/mp4v/mpeg4vid.vcxproj | 259 | ||||
-rw-r--r-- | Src/mp4v/mpeg4vid.vcxproj.filters | 56 | ||||
-rw-r--r-- | Src/mp4v/resource.h | 14 | ||||
-rw-r--r-- | Src/mp4v/version.rc2 | 39 |
16 files changed, 1584 insertions, 0 deletions
diff --git a/Src/mp4v/MFTDecoder.cpp b/Src/mp4v/MFTDecoder.cpp new file mode 100644 index 00000000..1a82cfd9 --- /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 00000000..997b24a9 --- /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 00000000..3ae0e226 --- /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 00000000..185cb84c --- /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 00000000..ff65f631 --- /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 00000000..ff7f1fe6 --- /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 00000000..eedd7e88 --- /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 00000000..6027af0b --- /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 00000000..9f96a341 --- /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 00000000..564cd736 --- /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 00000000..fcff7711 --- /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 00000000..e8f593b1 --- /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 00000000..bb899fb8 --- /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 00000000..99a22f44 --- /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 00000000..f753272a --- /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 00000000..912e8661 --- /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 |