diff options
Diffstat (limited to 'Src/aacdec-mft')
25 files changed, 2231 insertions, 0 deletions
diff --git a/Src/aacdec-mft/ADTSAACDecoder.cpp b/Src/aacdec-mft/ADTSAACDecoder.cpp new file mode 100644 index 00000000..30c181c6 --- /dev/null +++ b/Src/aacdec-mft/ADTSAACDecoder.cpp @@ -0,0 +1,266 @@ +#include "ADTSAACDecoder.h" +#include <nsaac/ADTSHeader.h> +#include "../nsutil/pcm.h" +#include <bfc/error.h> +#include <Mferror.h> + +ADTSAACDecoder::ADTSAACDecoder() +{ + predelay = 0; + useFloat = false; /* we'll fix during Initialize */ + gain=1.0f; /* we'll fix during Initialize */ + // get bps + bitsPerSample = 16; /* we'll fix during Initialize */ + allowRG = false; /* we'll fix during Initialize */ +} + +int ADTSAACDecoder::Initialize(bool forceMono, bool reverse_stereo, bool allowSurround, int maxBits, bool _allowRG, bool _useFloat, bool _useCRC) +{ + allowRG = _allowRG; + useFloat = _useFloat; + + if (_useFloat) { + bitsPerSample = 32; + } else if (maxBits >= 24) { + bitsPerSample = 24; + } else { + bitsPerSample = 16; + } + + decoder.Open(); + return adts::SUCCESS; +} + +bool ADTSAACDecoder::Open(ifc_mpeg_stream_reader *file) +{ + if (allowRG) + gain = file->MPEGStream_Gain(); + + return true; +} + +void ADTSAACDecoder::Close() +{ +} + +void ADTSAACDecoder::GetOutputParameters(size_t *numBits, int *numChannels, int *sampleRate) +{ + uint32_t local_sample_rate, local_channels; + decoder.GetOutputProperties(&local_sample_rate, &local_channels); + + *sampleRate = local_sample_rate; + *numChannels = local_channels; + *numBits = bitsPerSample; +} + +void ADTSAACDecoder::CalculateFrameSize(int *frameSize) +{ + size_t local_frame_size; + if (SUCCEEDED(decoder.OutputBlockSizeSamples(&local_frame_size))) { + *frameSize = (int)local_frame_size; + } else { + *frameSize = 0; + } +} + +void ADTSAACDecoder::Flush(ifc_mpeg_stream_reader *file) +{ + decoder.Flush(); +} + +size_t ADTSAACDecoder::GetCurrentBitrate() +{ + return 0; // TODO? +} + +size_t ADTSAACDecoder::GetDecoderDelay() +{ + return predelay; +} + +static int ADTSSync(const uint8_t *buffer, size_t bytes_in_buffer, size_t *header_position) +{ + for (size_t position=0;position<bytes_in_buffer;position++) + { + // find POTENTIAL sync + if (buffer[position] == 0xFF && bytes_in_buffer - position >= 7) + { + ADTSHeader header; + if (nsaac_adts_parse(&header, &buffer[position]) == NErr_Success) + { + int frame_length = (int)header.frame_length; + if (frame_length && bytes_in_buffer - position - frame_length >= 7) + { + ADTSHeader header2; + if (nsaac_adts_parse(&header2, &buffer[position+frame_length]) == NErr_Success) + { + // verify that parameters match + if (nsaac_adts_match(&header, &header2) != NErr_True) + return NErr_Changed; + + // do a dummy read to advance the stream + *header_position = position; + return NErr_Success; + } + } + else + { + /* not enough in the buffer to verify the next header */ + *header_position = position; + return NErr_NeedMoreData; + } + } + } + } + return NErr_False; +} + +static int ReturnIsEOF(ifc_mpeg_stream_reader *file) +{ + if (file->MPEGStream_EOF()) + return adts::ENDOFFILE; + else + return adts::NEEDMOREDATA; +} + +int ADTSAACDecoder::Internal_Decode(ifc_mpeg_stream_reader *file, + const void *input, size_t input_length, + unsigned __int8 *output, size_t outputSize, size_t *outputWritten) +{ + *outputWritten = outputSize; + if (SUCCEEDED(decoder.Feed(input, input_length))) { + HRESULT hr = decoder.Decode(output, outputWritten, bitsPerSample, useFloat, gain); + if (SUCCEEDED(hr)) { + if (*outputWritten == 0) { + return adts::NEEDMOREDATA; + } + return adts::SUCCESS; + } else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { + *outputWritten = 0; + return adts::SUCCESS; + } + } + return adts::FAILURE; +} + +int ADTSAACDecoder::Sync(ifc_mpeg_stream_reader *file, unsigned __int8 *output, size_t outputSize, size_t *outputWritten, size_t *bitrate) +{ + /* ok this will be interesting. we'll peek from the input buffer and try to synchronize on an ADTS header */ + uint8_t peek_buffer[16384]; + size_t bytes_read = 0; + if (file->MPEGStream_Peek(peek_buffer, sizeof(peek_buffer), &bytes_read) != 0) + { + return adts::FAILURE; + } + + size_t header_position=0; + int ret = ADTSSync(peek_buffer, bytes_read, &header_position); + if (ret == NErr_NeedMoreData) + { + // this one means we found one sync but not enough to verify the next frame + + // if the header was at the start of the block, then unfortunately this might be the LAST adts frame in the file, so let's just pass it the decoder and hope for the best + if (header_position != 0) + { + if (file->MPEGStream_EOF()) + return adts::ENDOFFILE; + + /* dummy read to advance the stream */ + file->MPEGStream_Read(peek_buffer, header_position, &header_position); + return adts::NEEDMOREDATA; + } + } + else if (ret == NErr_False) + { + if (file->MPEGStream_EOF()) + return adts::ENDOFFILE; + + // not even a potential sync found + /* dummy read to advance the stream */ + file->MPEGStream_Read(peek_buffer, bytes_read, &bytes_read); + return adts::NEEDMOREDATA; + } + else if (ret != NErr_Success) + { + if (file->MPEGStream_EOF()) + return adts::ENDOFFILE; + + return adts::FAILURE; + } + + ADTSHeader header; + if (nsaac_adts_parse(&header, &peek_buffer[header_position]) == NErr_Success) + { + /* all this error checking might be uncessary, since in theory we did a successful peek above. but you never know ... */ + if (file->MPEGStream_Read(peek_buffer, header_position, &bytes_read)) /* dummy read to advance the stream */ + return adts::FAILURE; + + if (bytes_read != header_position) + return ReturnIsEOF(file); + + if (file->MPEGStream_Read(peek_buffer, header.frame_length, &bytes_read)) /* read ADTS frame */ + return adts::FAILURE; + + if (bytes_read != header.frame_length) + return ReturnIsEOF(file); + + if (bytes_read < 7) /* bad header data? */ + return adts::FAILURE; + + /* ok, we've created the decoder, but we should really decode the frame to see if there's VBR, PS or MPEGS in it */ + size_t header_size = nsaac_adts_get_header_size(&header); + + int ret = Internal_Decode(file, peek_buffer, bytes_read, output, outputSize, outputWritten); + if (ret == adts::SUCCESS && *outputWritten == 0) { + return adts::NEEDMOREDATA; + } + return ret; + } + return adts::FAILURE; +} + +int ADTSAACDecoder::Decode(ifc_mpeg_stream_reader *file, unsigned __int8 *output, size_t outputSize, size_t *outputWritten, size_t *bitrate, size_t *endCut) +{ + HRESULT hr = decoder.Decode(output, outputWritten, bitsPerSample, useFloat, gain); + if (SUCCEEDED(hr) && *outputWritten) { + return adts::SUCCESS; + } + + uint8_t peek_buffer[8192]; + size_t bytes_read = 0; + + file->MPEGStream_Peek(peek_buffer, 7, &bytes_read); + if (bytes_read != 7) + return ReturnIsEOF(file); + + ADTSHeader header; + if (nsaac_adts_parse(&header, peek_buffer) == NErr_Success) + { + if (header.frame_length < 7) + return adts::FAILURE; + + file->MPEGStream_Peek(peek_buffer, header.frame_length, &bytes_read); + if (bytes_read != header.frame_length) + return ReturnIsEOF(file); + file->MPEGStream_Read(peek_buffer, header.frame_length, &bytes_read); + + size_t header_size = nsaac_adts_get_header_size(&header); + *bitrate = nsaac_adts_get_frame_bitrate(&header)/1000; + return Internal_Decode(file, peek_buffer, bytes_read, output, outputSize, outputWritten); + } + else + { + /* Resynchronize */ + return Sync(file, output, outputSize, outputWritten, bitrate); + } +} + +int ADTSAACDecoder::GetLayer() +{ + return 4; +} + +void ADTSAACDecoder::Release() +{ + delete this; +}
\ No newline at end of file diff --git a/Src/aacdec-mft/ADTSAACDecoder.h b/Src/aacdec-mft/ADTSAACDecoder.h new file mode 100644 index 00000000..417fdb9d --- /dev/null +++ b/Src/aacdec-mft/ADTSAACDecoder.h @@ -0,0 +1,39 @@ +#pragma once +#include "../Plugins/Input/in_mp3/adts.h" +#include "MFTDecoder.h" + +// {19450308-90D7-4E45-8A9D-DC71E67123E2} +static const GUID adts_aac_guid = +{ 0x19450308, 0x90d7, 0x4e45, { 0x8a, 0x9d, 0xdc, 0x71, 0xe6, 0x71, 0x23, 0xe2 } }; + +class ADTSAACDecoder : public adts +{ +public: + static const char *getServiceName() { return "MFT AAC ADTS Decoder"; } + static GUID getServiceGuid() { return adts_aac_guid; } + ADTSAACDecoder(); + int Initialize(bool forceMono, bool reverse_stereo, bool allowSurround, int maxBits, bool allowRG, bool _useFloat, bool _useCRC); + bool Open(ifc_mpeg_stream_reader *file); + void Close(); + void GetOutputParameters(size_t *numBits, int *numChannels, int *sampleRate); + void CalculateFrameSize(int *frameSize); + void Flush(ifc_mpeg_stream_reader *file); + size_t GetCurrentBitrate(); + size_t GetDecoderDelay(); + int Sync(ifc_mpeg_stream_reader *file, unsigned __int8 *output, size_t outputSize, size_t *outputWritten, size_t *bitrate); + int Decode(ifc_mpeg_stream_reader *file, unsigned __int8 *output, size_t outputSize, size_t *outputWritten, size_t *bitrate, size_t *endCut); + int GetLayer(); + void Release(); + +private: + int Internal_Decode(ifc_mpeg_stream_reader *file, const void *input, size_t input_length, unsigned __int8 *output, size_t outputSize, size_t *outputWritten); + + MFTDecoder decoder; + + int bitsPerSample; + float gain; + bool allowRG; + bool useFloat; + size_t predelay; + +};
\ No newline at end of file diff --git a/Src/aacdec-mft/AVIAACDecoder.cpp b/Src/aacdec-mft/AVIAACDecoder.cpp new file mode 100644 index 00000000..f2cf1591 --- /dev/null +++ b/Src/aacdec-mft/AVIAACDecoder.cpp @@ -0,0 +1,116 @@ +#include "AVIAACDecoder.h" +#include <math.h> +#include "../nsutil/pcm.h" + +int AVIDecoder::CreateAudioDecoder(const nsavi::AVIH *avi_header, + const nsavi::STRH *stream_header, const nsavi::STRF *stream_format, const nsavi::STRD *stream_data, + unsigned int preferred_bits, unsigned int max_channels, bool floating_point, + ifc_aviaudiodecoder **decoder) +{ + nsavi::audio_format *waveformat = (nsavi::audio_format *)stream_format; + + if (waveformat->format == nsavi::audio_format_aac) + { + AVIAACDecoder *aac_decoder = AVIAACDecoder::Create(waveformat, preferred_bits, max_channels, floating_point); + if (aac_decoder) + { + *decoder = aac_decoder; + return CREATEDECODER_SUCCESS; + } + return CREATEDECODER_SUCCESS; + } + + return CREATEDECODER_NOT_MINE; + +} + +#define CBCLASS AVIDecoder +START_DISPATCH; +CB(CREATE_AUDIO_DECODER, CreateAudioDecoder) +END_DISPATCH; +#undef CBCLASS + +AVIAACDecoder *AVIAACDecoder::Create(const nsavi::audio_format *waveformat, unsigned int preferred_bits, unsigned int max_channels, bool floating_point) +{ + if (!floating_point) + { + if (preferred_bits >= 24) + preferred_bits=24; + else + preferred_bits=16; + } + /*if (!max_channels) + max_channels = 8;*/ + + if (waveformat->extra_size_bytes) + { + AVIAACDecoder * decoder = new AVIAACDecoder(preferred_bits, floating_point); + if (decoder && SUCCEEDED(decoder->decoder.Open((const unsigned char *)(waveformat + 1), waveformat->extra_size_bytes))) { + return decoder; + } + delete decoder; + } + + return 0; +} + +AVIAACDecoder::AVIAACDecoder(unsigned int bps, bool floating_point) +: bps(bps), floating_point(floating_point) +{ +} + +int AVIAACDecoder::OutputFrameSize(size_t *frame_size) +{ + size_t local_frame_size; + if (FAILED(decoder.OutputBlockSizeSamples(&local_frame_size))) { + return AVI_FAILURE; + } + + *frame_size = local_frame_size; + return AVI_SUCCESS; +} + +int AVIAACDecoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat) +{ + uint32_t local_sample_rate, local_channels; + HRESULT hr = decoder.GetOutputProperties(&local_sample_rate, &local_channels); + if (FAILED(hr)) { + return AVI_FAILURE; + } + + *sampleRate = local_sample_rate; + *channels = local_channels; + *bitsPerSample = bps; + *isFloat = floating_point; + return AVI_SUCCESS; +} + +int AVIAACDecoder::DecodeChunk(uint16_t type, void **inputBuffer, size_t *inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes) +{ + if (SUCCEEDED(decoder.Feed(*inputBuffer, *inputBufferBytes)) + && SUCCEEDED(decoder.Decode(outputBuffer, outputBufferBytes, bps, false, 1.0))) { + *inputBufferBytes = 0; + return AVI_SUCCESS; + } + return AVI_FAILURE; +} + +void AVIAACDecoder::Flush() +{ + decoder.Flush(); +} + +void AVIAACDecoder::Close() +{ + delete this; +} + +#define CBCLASS AVIAACDecoder +START_DISPATCH; +CB(OUTPUT_FRAME_SIZE, OutputFrameSize) +CB(GET_OUTPUT_PROPERTIES, GetOutputProperties) +CB(DECODE_CHUNK, DecodeChunk) +VCB(FLUSH, Flush) +VCB(CLOSE, Close) +END_DISPATCH; +#undef CBCLASS
\ No newline at end of file diff --git a/Src/aacdec-mft/AVIAACDecoder.h b/Src/aacdec-mft/AVIAACDecoder.h new file mode 100644 index 00000000..f753a08a --- /dev/null +++ b/Src/aacdec-mft/AVIAACDecoder.h @@ -0,0 +1,40 @@ +#pragma once +#include "../Plugins/Input/in_avi/svc_avidecoder.h" +#include "../Plugins/Input/in_avi/ifc_aviaudiodecoder.h" +#include "MFTDecoder.h" + + +// {D6DB50A7-5E2F-4374-97B0-67CA707EB3CD} +static const GUID avi_aac_guid = +{ 0xd6db50a7, 0x5e2f, 0x4374, { 0x97, 0xb0, 0x67, 0xca, 0x70, 0x7e, 0xb3, 0xcd } }; + +class AVIDecoder : public svc_avidecoder +{ +public: + static const char *getServiceName() { return "MFT AAC AVI Decoder"; } + static GUID getServiceGuid() { return avi_aac_guid; } + int CreateAudioDecoder(const nsavi::AVIH *avi_header, const nsavi::STRH *stream_header, const nsavi::STRF *stream_format, const nsavi::STRD *stream_data, unsigned int preferred_bits, unsigned int max_channels, bool floating_point, ifc_aviaudiodecoder **decoder); +protected: + RECVS_DISPATCH; +}; + +class AVIAACDecoder : public ifc_aviaudiodecoder +{ +public: + AVIAACDecoder(unsigned int bps, bool floating_point); + static AVIAACDecoder *Create(const nsavi::audio_format *stream_format, unsigned int preferred_bits, unsigned int max_channels, bool floating_point); +protected: + RECVS_DISPATCH; +private: + /* ifc_aviaudiodecoder implementation */ + int OutputFrameSize(size_t *frame_size); + int GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat); + int DecodeChunk(uint16_t type, void **inputBuffer, size_t *inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes); + void Flush(); + void Close(); + + /* data */ + MFTDecoder decoder; + unsigned int bps; + bool floating_point; +};
\ No newline at end of file diff --git a/Src/aacdec-mft/FLVAACDecoder.cpp b/Src/aacdec-mft/FLVAACDecoder.cpp new file mode 100644 index 00000000..37cdb591 --- /dev/null +++ b/Src/aacdec-mft/FLVAACDecoder.cpp @@ -0,0 +1,115 @@ +#include "FLVAACDecoder.h" +#include <math.h> +#include "../nsutil/pcm.h" + +int FLVDecoder::CreateAudioDecoder(int stereo, int bits, int sample_rate, int format_type, ifc_flvaudiodecoder **decoder) +{ + if (format_type == FLV::AUDIO_FORMAT_AAC) + { + FLVAAC *aac = new FLVAAC(); + if (!aac) + { + return CREATEDECODER_FAILURE; + } + *decoder = aac; + return CREATEDECODER_SUCCESS; + } + return CREATEDECODER_NOT_MINE; +} + +int FLVDecoder::HandlesAudio(int format_type) +{ + if (format_type == FLV::AUDIO_FORMAT_AAC) + { + return CREATEDECODER_SUCCESS; + } + return CREATEDECODER_NOT_MINE; +} + +#define CBCLASS FLVDecoder +START_DISPATCH; +CB(CREATE_AUDIO_DECODER, CreateAudioDecoder) +CB(HANDLES_AUDIO, HandlesAudio) +END_DISPATCH; +#undef CBCLASS + +/* --- */ +FLVAAC::FLVAAC() +{ + bps = 16; + preDelay=0; + got_decoder_config = false; +} + +int FLVAAC::GetOutputFormat(unsigned int *sample_rate, unsigned int *channels, unsigned int *_bits) +{ + uint32_t local_sample_rate, local_channels; + HRESULT hr = decoder.GetOutputProperties(&local_sample_rate, &local_channels); + if (FAILED(hr)) { + return FLV_AUDIO_FAILURE; + } + + *sample_rate = local_sample_rate; + *channels = local_channels; + + *_bits = bps; + return FLV_AUDIO_SUCCESS; +} + +int FLVAAC::DecodeSample(const void *input_buffer, size_t input_buffer_bytes, void *samples, size_t *samples_size_bytes, double *bitrate) +{ + const uint8_t *type = (const uint8_t *)input_buffer; + if (type[0] == 0) + { + decoder.Open(type+1, input_buffer_bytes-1); + + got_decoder_config=true; + *samples_size_bytes=0; + return FLV_AUDIO_SUCCESS; + return FLV_AUDIO_FAILURE; + } + else if (type[0] == 1) + { + decoder.Feed(input_buffer, input_buffer_bytes); + decoder.Decode(samples, samples_size_bytes, bps, false, 1.0); + *bitrate = 0; + return FLV_AUDIO_SUCCESS; + + } + else + return FLV_AUDIO_FAILURE; +} + +void FLVAAC::Flush() +{ + decoder.Flush(); +} + +void FLVAAC::Close() +{ + delete this; +} + +int FLVAAC::Ready() +{ + return !!got_decoder_config; +} + +void FLVAAC::SetPreferences(unsigned int _max_channels, unsigned int preferred_bits) +{ + if (preferred_bits) + bps = preferred_bits; + + // TODO: max channels +} + +#define CBCLASS FLVAAC +START_DISPATCH; +CB(FLV_AUDIO_GETOUTPUTFORMAT, GetOutputFormat) +CB(FLV_AUDIO_DECODE, DecodeSample) +VCB(FLV_AUDIO_FLUSH, Flush) +VCB(FLV_AUDIO_CLOSE, Close) +CB(FLV_AUDIO_READY, Ready) +VCB(FLV_AUDIO_SETPREFERENCES, SetPreferences) +END_DISPATCH; +#undef CBCLASS diff --git a/Src/aacdec-mft/FLVAACDecoder.h b/Src/aacdec-mft/FLVAACDecoder.h new file mode 100644 index 00000000..12bfedc2 --- /dev/null +++ b/Src/aacdec-mft/FLVAACDecoder.h @@ -0,0 +1,43 @@ +#pragma once +#include "../Plugins/Input/in_flv/svc_flvdecoder.h" +#include "../Plugins/Input/in_flv/FLVAudioHeader.h" +#include "../Plugins/Input/in_flv/ifc_flvaudiodecoder.h" + +#include "MFTDecoder.h" + +// {B670EC35-1313-460a-A2EA-C7120AD18BAD} +static const GUID flv_aac_guid = +{ 0xb670ec35, 0x1313, 0x460a, { 0xa2, 0xea, 0xc7, 0x12, 0xa, 0xd1, 0x8b, 0xad } }; + + +class FLVDecoder : public svc_flvdecoder +{ +public: + static const char *getServiceName() { return "MFT AAC FLV Decoder"; } + static GUID getServiceGuid() { return flv_aac_guid; } + int CreateAudioDecoder(int stereo, int bits, int sample_rate, int format, ifc_flvaudiodecoder **decoder); + int HandlesAudio(int format_type); +protected: + RECVS_DISPATCH; +}; + +class FLVAAC : public ifc_flvaudiodecoder +{ +public: + FLVAAC(); + int GetOutputFormat(unsigned int *sample_rate, unsigned int *channels, unsigned int *bits); + int DecodeSample(const void *input_buffer, size_t input_buffer_bytes, void *samples, size_t *samples_size_bytes, double *bitrate); + void Flush(); + void Close(); + int Ready(); + void SetPreferences(unsigned int max_channels, unsigned int preferred_bits); +private: +/* data */ + MFTDecoder decoder; + unsigned int bps; + size_t preDelay; + bool got_decoder_config; + +protected: + RECVS_DISPATCH; +}; diff --git a/Src/aacdec-mft/MFTDecoder.cpp b/Src/aacdec-mft/MFTDecoder.cpp new file mode 100644 index 00000000..c0b32ec9 --- /dev/null +++ b/Src/aacdec-mft/MFTDecoder.cpp @@ -0,0 +1,209 @@ +#include "MFTDecoder.h" +#include "util.h" +#include "../nsutil/pcm.h" +#include <Mfapi.h> +#include <Mferror.h> + +static // Release the events that an MFT might allocate in IMFTransform::ProcessOutput(). +void ReleaseEventCollection(MFT_OUTPUT_DATA_BUFFER* pBuffers) +{ + + if (pBuffers->pEvents) + { + pBuffers->pEvents->Release(); + pBuffers->pEvents = NULL; + } + +} + +MFTDecoder::MFTDecoder() +{ + decoder=0; + output_buffer=0; + output_sample=0; +} + +MFTDecoder::~MFTDecoder() +{ + if (decoder) { + decoder->Release(); + } + decoder = 0; + + if (output_buffer) { + output_buffer->Release(); + } + output_buffer = 0; + + if (output_sample) { + output_sample->Release(); + } + output_sample = 0; +} + +HRESULT MFTDecoder::Open(const void *asc, size_t asc_bytes) +{ + HRESULT hr = CreateAACDecoder(&decoder, asc, asc_bytes); + if (SUCCEEDED(hr)) { + decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); + } + return hr; +} + +HRESULT MFTDecoder::Open() +{ + HRESULT hr = CreateADTSDecoder(&decoder); + if (SUCCEEDED(hr)) { + decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); + decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); + } + return hr; +} + +void MFTDecoder::Flush() +{ + if (decoder) { + decoder->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0); + } +} + +HRESULT MFTDecoder::GetOutputProperties(uint32_t *sampleRate, uint32_t *channels) +{ + HRESULT hr; + IMFMediaType *media_type; + UINT32 local_sample_rate, local_channels; + + if (!decoder) { + return E_FAIL; + } + + hr = decoder->GetOutputCurrentType(0, &media_type); + + if (FAILED(hr)) { + return hr; + } + + if (FAILED(hr=media_type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &local_sample_rate)) + || FAILED(hr=media_type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &local_channels))) { + media_type->Release(); + return hr; + } + + *sampleRate = local_sample_rate; + *channels = local_channels; + + return hr; +} + +HRESULT MFTDecoder::Feed(const void *inputBuffer, size_t inputBufferBytes) +{ + HRESULT hr; + if (inputBuffer && inputBufferBytes) { + IMFMediaBuffer *media_buffer=0; + IMFSample *media_sample=0; + MFCreateMemoryBuffer((DWORD)inputBufferBytes, &media_buffer); + MFCreateSample(&media_sample); + media_sample->AddBuffer(media_buffer); + + BYTE *buffer; + DWORD max_length, current_length; + media_buffer->Lock(&buffer, &max_length, ¤t_length); + memcpy(buffer, inputBuffer, inputBufferBytes); + + media_buffer->Unlock(); + media_buffer->SetCurrentLength((DWORD)inputBufferBytes); + + hr = decoder->ProcessInput(0, media_sample, 0); + media_sample->Release(); + media_buffer->Release(); + media_sample=0; + media_buffer=0; + } else { + decoder->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0); + decoder->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0); + } + return S_OK; +} + +HRESULT MFTDecoder::Decode(void *outputBuffer, size_t *outputBufferBytes, unsigned int bitsPerSample, bool isFloat, double gain) +{ + HRESULT hr; + + if (!output_sample) { + MFT_OUTPUT_STREAM_INFO output_stream_info; + hr = decoder->GetOutputStreamInfo(0, &output_stream_info); + if (FAILED(hr)) { + return hr; + } + + MFCreateMemoryBuffer(output_stream_info.cbSize, &output_buffer); + MFCreateSample(&output_sample); + output_sample->AddBuffer(output_buffer); + } + + output_buffer->SetCurrentLength(0); + MFT_OUTPUT_DATA_BUFFER output_data_buffer = {0, output_sample, 0, 0}; + DWORD status=0; + hr = decoder->ProcessOutput(0, 1, &output_data_buffer, &status); + if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { + *outputBufferBytes = 0; + return S_OK; + } else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { + AssociateFloat(decoder); + *outputBufferBytes = 0; + return hr; + } + IMFMediaBuffer *decimation_buffer; + hr = output_data_buffer.pSample->ConvertToContiguousBuffer(&decimation_buffer); + float *pcm; + DWORD max_length, current_length; + decimation_buffer->Lock((BYTE **)&pcm, &max_length, ¤t_length); + size_t num_samples = current_length / 4; + *outputBufferBytes = num_samples*bitsPerSample/8; + + if (!isFloat) + { + nsutil_pcm_FloatToInt_Interleaved_Gain(outputBuffer, pcm, bitsPerSample, num_samples, (float)gain); + } + else + { + for (size_t i = 0;i != num_samples;i++) + ((float *)outputBuffer)[i] = pcm[i] * (float)gain; + } + + decimation_buffer->Unlock(); + decimation_buffer->Release(); + + ReleaseEventCollection(&output_data_buffer); + + return S_OK; +} + +HRESULT MFTDecoder::OutputBlockSizeSamples(size_t *frameSize) +{ + HRESULT hr; + MFT_OUTPUT_STREAM_INFO output_stream_info; + + if (!decoder) { + return E_FAIL; + } + + hr = decoder->GetOutputStreamInfo(0, &output_stream_info); + if (FAILED(hr)) { + return hr; + } + + *frameSize = output_stream_info.cbSize; + return hr; +} + +bool MFTDecoder::AcceptingInput() +{ + DWORD flags; + if (decoder && SUCCEEDED(decoder->GetInputStatus(0, &flags))) { + if (flags & MFT_INPUT_STATUS_ACCEPT_DATA) { + return true; + } + } + return false; +}
\ No newline at end of file diff --git a/Src/aacdec-mft/MFTDecoder.h b/Src/aacdec-mft/MFTDecoder.h new file mode 100644 index 00000000..397702d5 --- /dev/null +++ b/Src/aacdec-mft/MFTDecoder.h @@ -0,0 +1,24 @@ +#pragma once +#include <mftransform.h> +#include <bfc/platform/types.h> + +// generic API for use by all decoder flavors (MP4, MKV, etc) + +class MFTDecoder +{ +public: + MFTDecoder(); + ~MFTDecoder(); + HRESULT Open(const void *asc, size_t asc_bytes); + HRESULT Open(); + void Flush(); + HRESULT GetOutputProperties(uint32_t *sampleRate, uint32_t *channels); + HRESULT Feed(const void *buffer, size_t bufferBytes); + HRESULT Decode(void *outputBuffer, size_t *outputBufferBytes, unsigned int bitsPerSample, bool useFloat, double gain); + HRESULT OutputBlockSizeSamples(size_t *frameSize); + bool AcceptingInput(); +private: + IMFTransform *decoder; + IMFMediaBuffer *output_buffer; + IMFSample *output_sample; +};
\ No newline at end of file diff --git a/Src/aacdec-mft/MKVAACDecoder.cpp b/Src/aacdec-mft/MKVAACDecoder.cpp new file mode 100644 index 00000000..49de01d7 --- /dev/null +++ b/Src/aacdec-mft/MKVAACDecoder.cpp @@ -0,0 +1,116 @@ +#include "MKVAACDecoder.h" +#include <math.h> +#include "../nsutil/pcm.h" + +MKVAACDecoder::MKVAACDecoder(unsigned int bps, bool floating_point) +: bps(bps), floating_point(floating_point) +{ + +} + +MKVAACDecoder *MKVAACDecoder::Create(const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data, unsigned int preferred_bits, unsigned int max_channels, bool floating_point) +{ + if (!floating_point) + { + if (preferred_bits >= 24) + preferred_bits=24; + else + preferred_bits=16; + } + /*if (!max_channels) + max_channels = 8;*/ + + if (track_entry_data->codec_private && track_entry_data->codec_private_len) + { + MKVAACDecoder *decoder = new MKVAACDecoder(preferred_bits, floating_point); + if (decoder && SUCCEEDED(decoder->decoder.Open(track_entry_data->codec_private, track_entry_data->codec_private_len))) { + return decoder; + } + delete decoder; + } + + return 0; +} + +int MKVAACDecoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat) +{ + uint32_t local_sample_rate, local_channels; + HRESULT hr = decoder.GetOutputProperties(&local_sample_rate, &local_channels); + if (FAILED(hr)) { + return MKV_FAILURE; + } + + *sampleRate = local_sample_rate; + *channels = local_channels; + + *bitsPerSample = bps; + *isFloat = floating_point; + return MKV_SUCCESS; +} + +void MKVAACDecoder::Flush() +{ + decoder.Flush(); +} + +int MKVAACDecoder::OutputFrameSize(size_t *frame_size) +{ + size_t local_frame_size; + if (FAILED(decoder.OutputBlockSizeSamples(&local_frame_size))) { + return MKV_FAILURE; + } + *frame_size = local_frame_size; + + return MKV_SUCCESS; +} + +void MKVAACDecoder::Close() +{ + delete this; +} + +int MKVAACDecoder::DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes) +{ + decoder.Feed(inputBuffer, inputBufferBytes); + decoder.Decode(outputBuffer, outputBufferBytes, bps, false, 1.0); + return MKV_SUCCESS; +} + +void MKVAACDecoder::EndOfStream() +{ + decoder.Feed(0, 0); +} + +#define CBCLASS MKVAACDecoder +START_DISPATCH; +CB(OUTPUT_FRAME_SIZE, OutputFrameSize) +CB(GET_OUTPUT_PROPERTIES, GetOutputProperties) +CB(DECODE_BLOCK, DecodeBlock) +VCB(FLUSH, Flush) +VCB(CLOSE, Close) +VCB(END_OF_STREAM, EndOfStream) +END_DISPATCH; +#undef CBCLASS + + +int MKVDecoder::CreateAudioDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data, unsigned int preferred_bits, unsigned int max_channels,bool floating_point, ifc_mkvaudiodecoder **decoder) +{ + if (!strcmp(codec_id, "A_AAC")) + { + MKVAACDecoder *aac_decoder = MKVAACDecoder::Create(track_entry_data, audio_data, preferred_bits, max_channels, floating_point); + if (aac_decoder) + { + *decoder = aac_decoder; + return CREATEDECODER_SUCCESS; + } + return CREATEDECODER_FAILURE; + } + + return CREATEDECODER_NOT_MINE; +} + +#define CBCLASS MKVDecoder +START_DISPATCH; +CB(CREATE_AUDIO_DECODER, CreateAudioDecoder) +END_DISPATCH; +#undef CBCLASS
\ No newline at end of file diff --git a/Src/aacdec-mft/MKVAACDecoder.h b/Src/aacdec-mft/MKVAACDecoder.h new file mode 100644 index 00000000..d4f6e73d --- /dev/null +++ b/Src/aacdec-mft/MKVAACDecoder.h @@ -0,0 +1,46 @@ +#pragma once +#include "../Plugins/Input/in_mkv/ifc_mkvaudiodecoder.h" +#include "MFTDecoder.h" +#include "../nsmkv/Tracks.h" +#include "../Plugins/Input/in_mkv/svc_mkvdecoder.h" + +// {437C68FA-2972-4ede-A157-CBD371E5E263} +static const GUID AACMKVGUID = +{ 0x437c68fa, 0x2972, 0x4ede, { 0xa1, 0x57, 0xcb, 0xd3, 0x71, 0xe5, 0xe2, 0x63 } }; + + +class MKVDecoder : public svc_mkvdecoder +{ +public: + static const char *getServiceName() { return "MFT AAC MKV Decoder"; } + static GUID getServiceGuid() { return AACMKVGUID; } + int CreateAudioDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data, unsigned int preferred_bits, unsigned int preferred_channels, bool floating_point, ifc_mkvaudiodecoder **decoder); +protected: + RECVS_DISPATCH; +}; + +class MKVAACDecoder : public ifc_mkvaudiodecoder +{ +public: + static MKVAACDecoder *Create(const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data, unsigned int preferred_bits, unsigned int max_channels, bool floating_point); + +protected: + RECVS_DISPATCH; +private: + /* ifc_mkvaudiodecoder implementation */ + int OutputFrameSize(size_t *frame_size); + int GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat); + int DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes); + void Flush(); + void Close(); + void EndOfStream(); // no more input, output anything you have buffered +private: + MKVAACDecoder(unsigned int bps, bool floating_point); + + /* internal implementation */ + + /* data */ + MFTDecoder decoder; + unsigned int bps; + bool floating_point; +};
\ No newline at end of file diff --git a/Src/aacdec-mft/MP4AACDecoder.cpp b/Src/aacdec-mft/MP4AACDecoder.cpp new file mode 100644 index 00000000..b431c067 --- /dev/null +++ b/Src/aacdec-mft/MP4AACDecoder.cpp @@ -0,0 +1,171 @@ +#include "MP4AACDecoder.h" +#include <Mferror.h> +#include <Mfapi.h> +#include "../external_dependencies/libmp4v2/mp4.h" +#include "util.h" +#include "../nsutil/pcm.h" + +MP4AACDecoder::MP4AACDecoder() +{ + isFloat = false; + gain=1.0f; + channels = 0; +} + +MP4AACDecoder::~MP4AACDecoder() +{ +} + +int MP4AACDecoder::OpenMP4(MP4FileHandle mp4_file, MP4TrackId mp4_track, size_t output_bits, size_t maxChannels, bool useFloat) +{ + HRESULT hr; + unsigned char *buffer; + uint32_t buffer_size; + + if (useFloat) { + this->bitsPerSample = 32; + } else if (output_bits) { + this->bitsPerSample = (unsigned int)output_bits; + } else { + this->bitsPerSample = 16; + } + + this->isFloat = useFloat; + + if (MP4GetTrackESConfiguration(mp4_file, mp4_track, (uint8_t **)&buffer, &buffer_size) && buffer) { + hr = decoder.Open(buffer, buffer_size); + if (SUCCEEDED(hr)) { + uint32_t local_sample_rate, local_channels; + hr = decoder.GetOutputProperties(&local_sample_rate, &local_channels); + if (SUCCEEDED(hr)) { + this->channels = local_channels; + return MP4_SUCCESS; + } + } + } + return MP4_FAILURE; +} + +void MP4AACDecoder::Close() +{ +} + +void MP4AACDecoder::Flush() +{ + decoder.Flush(); +} + +int MP4AACDecoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *_bitsPerSample) +{ + bool dummy; + return GetOutputPropertiesEx(sampleRate, channels, _bitsPerSample, &dummy); +} + +int MP4AACDecoder::GetOutputPropertiesEx(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *useFloat) +{ + HRESULT hr; + UINT32 local_sample_rate, local_channels; + + hr = decoder.GetOutputProperties(&local_sample_rate, &local_channels); + if (FAILED(hr)) { + return MP4_FAILURE; + } + + *sampleRate = local_sample_rate; + *channels = local_channels; + *bitsPerSample = this->bitsPerSample; + *useFloat = this->isFloat; + + return MP4_SUCCESS; +} + +int MP4AACDecoder::DecodeSample(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes) +{ + HRESULT hr; + + hr = decoder.Feed(inputBuffer, inputBufferBytes); + if (FAILED(hr)) { + return MP4_FAILURE; + } + + hr = decoder.Decode(outputBuffer, outputBufferBytes, this->bitsPerSample, this->isFloat, this->gain); + if (FAILED(hr)) { + return MP4_FAILURE; + } + + return MP4_SUCCESS; +} + +int MP4AACDecoder::OutputFrameSize(size_t *frameSize) +{ + if (channels == 0) { + return MP4_FAILURE; + } + + size_t local_frame_size; + if (FAILED(decoder.OutputBlockSizeSamples(&local_frame_size))) { + return MP4_FAILURE; + } + *frameSize = local_frame_size / channels; + + return MP4_SUCCESS; +} + +int MP4AACDecoder::CanHandleCodec(const char *codecName) +{ + return !strcmp(codecName, "mp4a"); +} + +int MP4AACDecoder::CanHandleType(uint8_t type) +{ + switch (type) + { + case MP4_TYPE_MPEG4_AUDIO: + return 1; + case MP4_TYPE_MPEG2_AAC_LC_AUDIO: + return 1; + default: + return 0; + } +} + +int MP4AACDecoder::CanHandleMPEG4Type(uint8_t type) +{ + switch (type) + { + case MP4_MPEG4_TYPE_AAC_LC_AUDIO: + case MP4_MPEG4_TYPE_AAC_HE_AUDIO: + case MP4_MPEG4_TYPE_PARAMETRIC_STEREO: + return 1; + default: + return 0; + } +} + +void MP4AACDecoder::EndOfStream() +{ + decoder.Feed(0, 0); +} + +#ifdef CBCLASS +#undef CBCLASS +#endif + +#define CBCLASS MP4AACDecoder +START_DISPATCH; +CB(MPEG4_AUDIO_OPENMP4, OpenMP4) +#if 0 +CB(MPEG4_AUDIO_BITRATE, GetCurrentBitrate) +#endif + +CB(MPEG4_AUDIO_FRAMESIZE, OutputFrameSize) +CB(MPEG4_AUDIO_OUTPUTINFO, GetOutputProperties) +CB(MPEG4_AUDIO_OUTPUTINFO_EX, GetOutputPropertiesEx) +CB(MPEG4_AUDIO_DECODE, DecodeSample) +VCB(MPEG4_AUDIO_FLUSH, Flush) +VCB(MPEG4_AUDIO_CLOSE, Close) +CB(MPEG4_AUDIO_HANDLES_CODEC, CanHandleCodec) +CB(MPEG4_AUDIO_HANDLES_TYPE, CanHandleType) +CB(MPEG4_AUDIO_HANDLES_MPEG4_TYPE, CanHandleMPEG4Type) +CB(MPEG4_AUDIO_SET_GAIN, SetGain) +END_DISPATCH;
\ No newline at end of file diff --git a/Src/aacdec-mft/MP4AACDecoder.h b/Src/aacdec-mft/MP4AACDecoder.h new file mode 100644 index 00000000..71677075 --- /dev/null +++ b/Src/aacdec-mft/MP4AACDecoder.h @@ -0,0 +1,40 @@ +#pragma once +#include "../Plugins/Input/in_mp4/mpeg4audio.h" +#include "MFTDecoder.h" + +// {3C0B6E1B-0C21-4716-B8D6-C7665CBC90E9} +static const GUID mp4_aac_guid = +{ 0x3c0b6e1b, 0xc21, 0x4716, { 0xb8, 0xd6, 0xc7, 0x66, 0x5c, 0xbc, 0x90, 0xe9 } }; + + +class MP4AACDecoder : public MP4AudioDecoder +{ +public: + static const char *getServiceName() { return "MFT AAC MP4 Decoder"; } + static GUID getServiceGuid() { return mp4_aac_guid; } + MP4AACDecoder(); + ~MP4AACDecoder(); + int OpenMP4(MP4FileHandle mp4_file, MP4TrackId mp4_track, size_t output_bits, size_t maxChannels, bool useFloat); + void Close(); + int GetCurrentBitrate(unsigned int *bitrate); + int AudioSpecificConfiguration(void *buffer, size_t buffer_size); // reads ASC block from mp4 file + void Flush(); + int GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *_bitsPerSample); + int GetOutputPropertiesEx(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *useFloat); + int DecodeSample(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes); + int OutputFrameSize(size_t *frameSize); + int CanHandleCodec(const char *codecName); + int CanHandleType(uint8_t type); + int CanHandleMPEG4Type(uint8_t type); + int SetGain(float _gain) { gain=_gain; return MP4_SUCCESS; } + void EndOfStream(); +private: + MFTDecoder decoder; + + unsigned int bitsPerSample; + bool isFloat; + float gain; + unsigned int channels; +protected: + RECVS_DISPATCH; +}; diff --git a/Src/aacdec-mft/NSVAACDecoder.cpp b/Src/aacdec-mft/NSVAACDecoder.cpp new file mode 100644 index 00000000..4fd067e8 --- /dev/null +++ b/Src/aacdec-mft/NSVAACDecoder.cpp @@ -0,0 +1,121 @@ +#include "NSVAACDecoder.h" + +#include <assert.h> +#include "api.h" +#include "../nsv/nsvlib.h" +#include "api.h" +#include "../nsv/nsvlib.h" +#include "../nsv/dec_if.h" +#include <string.h> +#include <bfc/platform/export.h> +#include "NSVAACDecoder.h" +#include <bfc/error.h> +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +NSVAACDecoder *NSVAACDecoder::CreateDecoder() +{ + NSVAACDecoder *decoder=0; + WASABI_API_MEMMGR->New(&decoder); + if (!decoder) + { + return 0; + } + decoder->Initialize(); + return decoder; +} + +NSVAACDecoder::NSVAACDecoder() +{ + source_position=0; + out_left=0; + in_position=0; +} + +NSVAACDecoder::~NSVAACDecoder() +{ + +} + +void NSVAACDecoder::Initialize() +{ + decoder.Open(); +} + +void NSVAACDecoder::flush() +{ + decoder.Flush(); +} + +// returns -1 on error, 0 on success (done with data in 'in'), 1 on success +// but to pass 'in' again next time around. +int NSVAACDecoder::decode(void *in, int in_len, void *out, int *out_len, unsigned int out_fmt[8]) +{ + HRESULT hr; + size_t local_out_len = *out_len; + if (SUCCEEDED(decoder.Decode(out, &local_out_len, 16, false, 1.0))) { + *out_len = (int)local_out_len; + if (local_out_len) { + uint32_t local_sample_rate, local_channels; + if (SUCCEEDED(decoder.GetOutputProperties(&local_sample_rate, &local_channels))) { + + out_fmt[0] = NSV_MAKETYPE('P', 'C', 'M', ' '); + out_fmt[1] = local_sample_rate; + out_fmt[2] = local_channels; + out_fmt[3] = 16; + } + return 1; + } + } + + hr = decoder.Feed(in, in_len); + if (FAILED(hr)) { + hr=hr; + } + + + local_out_len = *out_len; + if (SUCCEEDED(decoder.Decode(out, &local_out_len, 16, false, 1.0))) { + *out_len = (int)local_out_len; + if (local_out_len) { + uint32_t local_sample_rate, local_channels; + if (SUCCEEDED(decoder.GetOutputProperties(&local_sample_rate, &local_channels))) { + + out_fmt[0] = NSV_MAKETYPE('P', 'C', 'M', ' '); + out_fmt[1] = local_sample_rate; + out_fmt[2] = local_channels; + out_fmt[3] = 16; + } + } + } else { + *out_len = 0; + } + return 0; +} + + + +IAudioDecoder *NSVDecoder::CreateAudioDecoder(FOURCC format, IAudioOutput **output) +{ + switch (format) + { + case NSV_MAKETYPE('A', 'A', 'C', ' ') : + case NSV_MAKETYPE('A', 'A', 'C', 'P'): + case NSV_MAKETYPE('A', 'P', 'L', ' '): + { + NSVAACDecoder *dec = NSVAACDecoder::CreateDecoder(); + return dec; + } + + default: + return 0; + } +} + + +#define CBCLASS NSVDecoder +START_DISPATCH; +CB(SVC_NSVFACTORY_CREATEAUDIODECODER, CreateAudioDecoder) +END_DISPATCH; +#undef CBCLASS diff --git a/Src/aacdec-mft/NSVAACDecoder.h b/Src/aacdec-mft/NSVAACDecoder.h new file mode 100644 index 00000000..3c13e14b --- /dev/null +++ b/Src/aacdec-mft/NSVAACDecoder.h @@ -0,0 +1,45 @@ +#pragma once +#include "../nsv/dec_if.h" +#include "MFTDecoder.h" +#include <bfc/platform/types.h> +//#include "ADTSHeader.h" +#include "../nsv/svc_nsvFactory.h" + +// {E890E15C-A6D8-4ed9-9204-85C77AB80C53} +static const GUID NSV_AAC_GUID = +{ 0xe890e15c, 0xa6d8, 0x4ed9, { 0x92, 0x4, 0x85, 0xc7, 0x7a, 0xb8, 0xc, 0x53 } }; + +class NSVDecoder : public svc_nsvFactory +{ +public: + static const char *getServiceName() { return "MFT AAC NSV Decoder"; } + static GUID getServiceGuid() { return NSV_AAC_GUID; } + IAudioDecoder *CreateAudioDecoder(FOURCC format, IAudioOutput **output) override; + +protected: + RECVS_DISPATCH; +}; + +class NSVAACDecoder : public IAudioDecoder +{ +public: + static NSVAACDecoder *CreateDecoder(); + NSVAACDecoder(); + ~NSVAACDecoder(); + void Initialize(); + int decode(void *in, int in_len, void *out, int *out_len, unsigned int out_fmt[8]); + void flush(); + bool OK(); + +private: + void FillOutputFormat(unsigned int out_fmt[8]); + void CopyToOutput(void *out, int *out_len); + +private: + /* data */ + MFTDecoder decoder; + int in_position; + int out_left; + size_t source_position; +}; + diff --git a/Src/aacdec-mft/aacdec-mft.rc b/Src/aacdec-mft/aacdec-mft.rc new file mode 100644 index 00000000..fcff7711 --- /dev/null +++ b/Src/aacdec-mft/aacdec-mft.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/aacdec-mft/aacdec-mft.sln b/Src/aacdec-mft/aacdec-mft.sln new file mode 100644 index 00000000..8e22690a --- /dev/null +++ b/Src/aacdec-mft/aacdec-mft.sln @@ -0,0 +1,53 @@ + +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}") = "aacdec-mft", "aacdec-mft.vcxproj", "{F6962367-6A6C-4E7D-B661-B767E904F451}" + ProjectSection(ProjectDependencies) = postProject + {DABE6307-F8DD-416D-9DAC-673E2DECB73F} = {DABE6307-F8DD-416D-9DAC-673E2DECB73F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nsutil", "..\nsutil\nsutil.vcxproj", "{DABE6307-F8DD-416D-9DAC-673E2DECB73F}" +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 + {F6962367-6A6C-4E7D-B661-B767E904F451}.Debug|Win32.ActiveCfg = Debug|Win32 + {F6962367-6A6C-4E7D-B661-B767E904F451}.Debug|Win32.Build.0 = Debug|Win32 + {F6962367-6A6C-4E7D-B661-B767E904F451}.Debug|x64.ActiveCfg = Debug|x64 + {F6962367-6A6C-4E7D-B661-B767E904F451}.Debug|x64.Build.0 = Debug|x64 + {F6962367-6A6C-4E7D-B661-B767E904F451}.Release|Win32.ActiveCfg = Release|Win32 + {F6962367-6A6C-4E7D-B661-B767E904F451}.Release|x64.ActiveCfg = Release|x64 + {F6962367-6A6C-4E7D-B661-B767E904F451}.Release|x64.Build.0 = Release|x64 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|Win32.ActiveCfg = Debug|Win32 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|Win32.Build.0 = Debug|Win32 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|x64.ActiveCfg = Debug|x64 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|x64.Build.0 = Debug|x64 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|Win32.ActiveCfg = Release|Win32 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|Win32.Build.0 = Release|Win32 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|x64.ActiveCfg = Release|x64 + {DABE6307-F8DD-416D-9DAC-673E2DECB73F}.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 = {FC646532-2050-40A5-A2AB-F699F1C071C4} + EndGlobalSection +EndGlobal diff --git a/Src/aacdec-mft/aacdec-mft.vcxproj b/Src/aacdec-mft/aacdec-mft.vcxproj new file mode 100644 index 00000000..d692e567 --- /dev/null +++ b/Src/aacdec-mft/aacdec-mft.vcxproj @@ -0,0 +1,274 @@ +<?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"> + <ProjectGuid>{F6962367-6A6C-4E7D-B661-B767E904F451}</ProjectGuid> + <RootNamespace>aacdec</RootNamespace> + <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" 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> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|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> + <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> + <TargetName>aacdec</TargetName> + <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> + <TargetName>aacdec</TargetName> + <TargetExt>.w5s</TargetExt> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <TargetName>aacdec</TargetName> + <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> + <TargetName>aacdec</TargetName> + <TargetExt>.w5s</TargetExt> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <VcpkgConfiguration>Debug</VcpkgConfiguration> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </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|x64'"> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + <VcpkgConfiguration>Debug</VcpkgConfiguration> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>../Wasabi;../replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;AACDECMFT_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>mf.lib;mfuuid.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;../replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;AACDECMFT_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>mf.lib;mfuuid.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>MinSpace</Optimization> + <FavorSizeOrSpeed>Size</FavorSizeOrSpeed> + <IntrinsicFunctions>true</IntrinsicFunctions> + <AdditionalIncludeDirectories>../Wasabi;../replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;AACDECMFT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>None</DebugInformationFormat> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Link> + <AdditionalDependencies>mf.lib;mfuuid.lib;mfplat.lib;wmcodecdspuuid.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <GenerateDebugInformation>false</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <ImportLibrary>$(ProjectDir)x86_Release\$(TargetName).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>MinSpace</Optimization> + <FavorSizeOrSpeed>Size</FavorSizeOrSpeed> + <IntrinsicFunctions>true</IntrinsicFunctions> + <AdditionalIncludeDirectories>../Wasabi;../replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;AACDECMFT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>None</DebugInformationFormat> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Link> + <AdditionalDependencies>mf.lib;mfuuid.lib;mfplat.lib;wmcodecdspuuid.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <GenerateDebugInformation>false</GenerateDebugInformation> + <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <ImportLibrary>$(ProjectDir)x64_Release\$(TargetName).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="..\nsutil\nsutil.vcxproj"> + <Project>{dabe6307-f8dd-416d-9dac-673e2decb73f}</Project> + </ProjectReference> + <ProjectReference Include="..\Wasabi\Wasabi.vcxproj"> + <Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\replicant\nsaac\ADTSHeader.c" /> + <ClCompile Include="ADTSAACDecoder.cpp" /> + <ClCompile Include="api.cpp" /> + <ClCompile Include="AVIAACDecoder.cpp" /> + <ClCompile Include="FLVAACDecoder.cpp" /> + <ClCompile Include="main.cpp" /> + <ClCompile Include="mft-util.cpp" /> + <ClCompile Include="MFTDecoder.cpp" /> + <ClCompile Include="MKVAACDecoder.cpp" /> + <ClCompile Include="MP4AACDecoder.cpp" /> + <ClCompile Include="NSVAACDecoder.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\replicant\nsaac\ADTSHeader.h" /> + <ClInclude Include="ADTSAACDecoder.h" /> + <ClInclude Include="api.h" /> + <ClInclude Include="AVIAACDecoder.h" /> + <ClInclude Include="FLVAACDecoder.h" /> + <ClInclude Include="MFTDecoder.h" /> + <ClInclude Include="MKVAACDecoder.h" /> + <ClInclude Include="MP4AACDecoder.h" /> + <ClInclude Include="NSVAACDecoder.h" /> + <ClInclude Include="resource.h" /> + <ClInclude Include="util.h" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="aacdec-mft.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/Src/aacdec-mft/aacdec-mft.vcxproj.filters b/Src/aacdec-mft/aacdec-mft.vcxproj.filters new file mode 100644 index 00000000..7eb9cc29 --- /dev/null +++ b/Src/aacdec-mft/aacdec-mft.vcxproj.filters @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="ADTSAACDecoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\replicant\nsaac\ADTSHeader.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="api.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="AVIAACDecoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="FLVAACDecoder.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="mft-util.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="MKVAACDecoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="MP4AACDecoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="NSVAACDecoder.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="resource.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="ADTSAACDecoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\replicant\nsaac\ADTSHeader.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="api.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="AVIAACDecoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="FLVAACDecoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="MFTDecoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="MKVAACDecoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="MP4AACDecoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="NSVAACDecoder.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="util.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <Filter Include="Header Files"> + <UniqueIdentifier>{fba2fb29-46f5-449a-a2d4-f599c329c299}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files"> + <UniqueIdentifier>{f5dc361a-609c-422d-a515-244e8f22edf1}</UniqueIdentifier> + </Filter> + <Filter Include="Ressource Files"> + <UniqueIdentifier>{6fca69fe-c362-4e6d-a1d2-307925c9cbbe}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="aacdec-mft.rc"> + <Filter>Ressource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/Src/aacdec-mft/api.cpp b/Src/aacdec-mft/api.cpp new file mode 100644 index 00000000..7072cfc3 --- /dev/null +++ b/Src/aacdec-mft/api.cpp @@ -0,0 +1,5 @@ +#include "api.h" + +api_service *WASABI_API_SVC=0; +api_config *AGAVE_API_CONFIG=0; +api_memmgr *WASABI_API_MEMMGR=0; diff --git a/Src/aacdec-mft/api.h b/Src/aacdec-mft/api.h new file mode 100644 index 00000000..482f7ec6 --- /dev/null +++ b/Src/aacdec-mft/api.h @@ -0,0 +1,12 @@ +#pragma once + +#include <api/service/api_service.h> +extern api_service *serviceManager; +#define WASABI_API_SVC serviceManager + + +#include "../Agave/Config/api_config.h" + +#include <api/memmgr/api_memmgr.h> +extern api_memmgr *memmgrApi; +#define WASABI_API_MEMMGR memmgrApi diff --git a/Src/aacdec-mft/main.cpp b/Src/aacdec-mft/main.cpp new file mode 100644 index 00000000..51a4693a --- /dev/null +++ b/Src/aacdec-mft/main.cpp @@ -0,0 +1,79 @@ +#include "api.h" + +#include "../nu/Singleton.h" +#include "../nu/factoryt.h" +#include "AVIAACDecoder.h" +#include "FLVAACDecoder.h" +#include "MKVAACDecoder.h" +#include "MP4AACDecoder.h" +#include "ADTSAACDecoder.h" +#include "NSVAACDecoder.h" +#include <bfc/platform/export.h> +#include "../Agave/Component/ifc_wa5component.h" +#include "../nu/ServiceBuilder.h" + +class AACDecoderComponent : public ifc_wa5component +{ +public: + void RegisterServices(api_service *service); + int RegisterServicesSafeModeOk(); + void DeregisterServices(api_service *service); + +protected: + RECVS_DISPATCH; +}; + +static SingletonServiceFactory<svc_avidecoder, AVIDecoder> avi_factory; +static AVIDecoder avi_decoder; +static SingletonServiceFactory<svc_mkvdecoder, MKVDecoder> mkv_factory; +static MKVDecoder mkv_decoder; +static SingletonServiceFactory<svc_flvdecoder, FLVDecoder> flv_factory; +static FLVDecoder flv_decoder; +static ServiceFactoryT<MP4AudioDecoder, MP4AACDecoder> mp4_factory; +static ServiceFactoryT<adts, ADTSAACDecoder> adts_factory; +static NSVDecoder nsv_decoder; +static SingletonServiceFactory<svc_nsvFactory, NSVDecoder> nsv_factory; + +void AACDecoderComponent::RegisterServices(api_service *service) +{ + WASABI_API_SVC = service; + avi_factory.Register(WASABI_API_SVC, &avi_decoder); + mkv_factory.Register(WASABI_API_SVC, &mkv_decoder); + flv_factory.Register(WASABI_API_SVC, &flv_decoder); + nsv_factory.Register(WASABI_API_SVC, &nsv_decoder); + mp4_factory.Register(WASABI_API_SVC); + adts_factory.Register(WASABI_API_SVC); + ServiceBuild(WASABI_API_SVC, AGAVE_API_CONFIG, AgaveConfigGUID); + ServiceBuild(WASABI_API_SVC, WASABI_API_MEMMGR, memMgrApiServiceGuid); +} + +void AACDecoderComponent::DeregisterServices(api_service *service) +{ + avi_factory.Deregister(WASABI_API_SVC); + mkv_factory.Deregister(WASABI_API_SVC); + mp4_factory.Deregister(WASABI_API_SVC); + flv_factory.Deregister(WASABI_API_SVC); + nsv_factory.Deregister(WASABI_API_SVC); + adts_factory.Deregister(WASABI_API_SVC); + ServiceRelease(WASABI_API_SVC, AGAVE_API_CONFIG, AgaveConfigGUID); + ServiceRelease(WASABI_API_SVC, WASABI_API_MEMMGR, memMgrApiServiceGuid); +} + +int AACDecoderComponent::RegisterServicesSafeModeOk() +{ + return 1; +} + +AACDecoderComponent aac_decoder_component; +extern "C" DLLEXPORT ifc_wa5component *GetWinamp5SystemComponent() +{ + return &aac_decoder_component; +} + +#define CBCLASS AACDecoderComponent +START_DISPATCH; +VCB(API_WA5COMPONENT_REGISTERSERVICES, RegisterServices) +CB(15, RegisterServicesSafeModeOk) +VCB(API_WA5COMPONENT_DEREEGISTERSERVICES, DeregisterServices) +END_DISPATCH; +#undef CBCLASS
\ No newline at end of file diff --git a/Src/aacdec-mft/mft-util.cpp b/Src/aacdec-mft/mft-util.cpp new file mode 100644 index 00000000..7a71b665 --- /dev/null +++ b/Src/aacdec-mft/mft-util.cpp @@ -0,0 +1,191 @@ +#include "util.h" +#include <bfc/platform/types.h> +#include <mferror.h> +#include <mftransform.h> +#include <wmcodecdsp.h> +#include <Mfidl.h> +#include <Mfapi.h> + +struct AACUserData { + WORD wPayloadType; + WORD wAudioProfileLevelIndication; + WORD wStructType; + WORD wReserved1; + DWORD dwReserved2; + uint8_t buffer[16]; +}; + +HRESULT GetAACCodec(IMFTransform **pDecoder) +{ + HRESULT hr = S_OK; + UINT32 count = 0; + + IMFActivate **ppActivate = NULL; // Array of activation objects. + + MFT_REGISTER_TYPE_INFO info = { MFMediaType_Audio, MFAudioFormat_AAC }; + + UINT32 unFlags = MFT_ENUM_FLAG_SYNCMFT | + MFT_ENUM_FLAG_LOCALMFT | + MFT_ENUM_FLAG_SORTANDFILTER; + + hr = MFTEnumEx( + MFT_CATEGORY_AUDIO_DECODER, + unFlags, + &info, // Input type + NULL, // Output type + &ppActivate, + &count + ); + + + if (SUCCEEDED(hr) && count == 0) + { + hr = MF_E_TOPO_CODEC_NOT_FOUND; + } + + // Create the first decoder in the list. + + if (SUCCEEDED(hr)) + { + hr = ppActivate[0]->ActivateObject(IID_PPV_ARGS(pDecoder)); + } + + for (UINT32 i = 0; i < count; i++) + { + ppActivate[i]->Release(); + } + CoTaskMemFree(ppActivate); + return hr; +} + +bool AssociateFloat(IMFTransform *decoder) +{ + IMFMediaType *media_type; + DWORD index=0; + for (;;) + { + GUID subtype; + UINT32 bps; + HRESULT hr = decoder->GetOutputAvailableType(0, index++, &media_type); + if (hr != S_OK) + return false; + + if (media_type->GetGUID(MF_MT_SUBTYPE, &subtype) != S_OK + || media_type->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &bps) != S_OK) + { + media_type->Release(); + return false; + } + + if (subtype == MFAudioFormat_Float && bps == 32) + { + hr = decoder->SetOutputType(0, media_type, 0); + media_type->Release(); + + return true; + } + media_type->Release(); + } +} + +static uint32_t SampleRateForASC(const void *asc, size_t aacConfigLength) +{ + const uint8_t *pAacConfig = (const uint8_t *)asc; + const uint32_t samplingRates[]={96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,0}; + int index; + if (aacConfigLength >= 5 && (pAacConfig[4] >> 7) == 1) + { + index = (pAacConfig[4] >> 3) & 0x7; + + } else if (aacConfigLength >= 2) { + index = ((pAacConfig[0] & 0x7) << 1) | (pAacConfig[1] >> 7); // bits 5-8 + } else { + index = 12; + } + return samplingRates[index]; +} + +HRESULT CreateAACDecoder(IMFTransform **pDecoder, const void *asc, size_t asc_bytes) +{ + HRESULT hr; + IMFMediaType *media_type; + + hr = GetAACCodec(pDecoder); + if (FAILED(hr)) { + return hr; + } + + hr = MFCreateMediaType(&media_type); + if (FAILED(hr)) { + return hr; + } + hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); + hr = media_type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC); + // + hr = media_type->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 0); // The stream contains raw_data_block elements only. + uint8_t profile_level =0xFE;// MP4GetAudioProfileLevel(mp4_file); + hr = media_type->SetUINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, profile_level); + media_type->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, SampleRateForASC(asc, asc_bytes)); + + // this is such a pain in the ass, it's part of an HEAACWAVEINFO struct packed together with the ASC data + AACUserData aacinfo; + aacinfo.wPayloadType = 0; + aacinfo.wAudioProfileLevelIndication = profile_level; + aacinfo.wStructType = 0; + + if (asc && asc_bytes) { + if (asc_bytes > 16) { // don't overrun the buffer + return E_FAIL; + } + memcpy(aacinfo.buffer, asc, asc_bytes); + + hr = media_type->SetBlob(MF_MT_USER_DATA, (const UINT8 *)&aacinfo, 12+(UINT)asc_bytes); + } + + hr = (*pDecoder)->SetInputType(0, media_type, 0); + if (FAILED(hr)) { + return hr; + } + media_type->Release(); + media_type=0; + + AssociateFloat(*pDecoder); + + return S_OK; +} + +HRESULT CreateADTSDecoder(IMFTransform **pDecoder) +{ + HRESULT hr; + IMFMediaType *media_type; + + hr = GetAACCodec(pDecoder); + if (FAILED(hr)) { + return hr; + } + + hr = MFCreateMediaType(&media_type); + if (FAILED(hr)) { + return hr; + } + hr = media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); + hr = media_type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC); + hr = media_type->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 1); // ADTS + //hr = media_type->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16); // 16 bits per sample + uint8_t profile_level =0xFE;// MP4GetAudioProfileLevel(mp4_file); + hr = media_type->SetUINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, profile_level); + + const BYTE user_data[] = {0x01, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + hr = media_type->SetBlob(MF_MT_USER_DATA, user_data, sizeof(user_data)); + + hr = (*pDecoder)->SetInputType(0, media_type, 0); + if (FAILED(hr)) { + return hr; + } + media_type->Release(); + media_type=0; + + AssociateFloat(*pDecoder); + + return S_OK; +} diff --git a/Src/aacdec-mft/resource.h b/Src/aacdec-mft/resource.h new file mode 100644 index 00000000..39c0e23e --- /dev/null +++ b/Src/aacdec-mft/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by aacdec-mft.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/aacdec-mft/util.h b/Src/aacdec-mft/util.h new file mode 100644 index 00000000..6f7cf85c --- /dev/null +++ b/Src/aacdec-mft/util.h @@ -0,0 +1,8 @@ +#pragma once +#include <mftransform.h> +#include <bfc/platform/types.h> + +HRESULT GetAACCodec(IMFTransform **pDecoder); +HRESULT CreateAACDecoder(IMFTransform **pDecoder, const void *asc, size_t asc_bytes); +HRESULT CreateADTSDecoder(IMFTransform **pDecoder); +bool AssociateFloat(IMFTransform *decoder);
\ No newline at end of file diff --git a/Src/aacdec-mft/version.rc2 b/Src/aacdec-mft/version.rc2 new file mode 100644 index 00000000..5bb1e674 --- /dev/null +++ b/Src/aacdec-mft/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", "aacdec-mft.w5s" + VALUE "LegalCopyright", "Copyright © 2015-2019 Ben Allison" + VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA" + VALUE "OriginalFilename", "aacdec.w5s" + VALUE "ProductName", "Winamp AAC Decoder Service" + VALUE "ProductVersion", STR_WINAMP_PRODUCTVER + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END |