diff options
author | v0lt <v0lt@users.sourceforge.net> | 2012-06-12 11:51:18 +0400 |
---|---|---|
committer | v0lt <v0lt@users.sourceforge.net> | 2012-06-12 11:51:18 +0400 |
commit | 3729916843a388a4df707403565504bd01ac5f51 (patch) | |
tree | ec66a0a2ede07ea392e8998bde253ceed7422e0d /src | |
parent | 9262a576c096e20eff4c235e68e73f37077a736b (diff) |
MpaDecFilter: use ffmpeg instead of libflac for FLAC decoding
git-svn-id: https://mpc-hc.svn.sourceforge.net/svnroot/mpc-hc/trunk@5097 10f7b99b-c216-0410-bff0-8a66a9350fd8
Diffstat (limited to 'src')
-rw-r--r-- | src/filters/transform/MpaDecFilter/MpaDecFilter.cpp | 178 | ||||
-rw-r--r-- | src/filters/transform/MpaDecFilter/MpaDecFilter.h | 24 | ||||
-rw-r--r-- | src/mpc-hc/FilterEnum.h | 2 | ||||
-rw-r--r-- | src/mpc-hc/InternalFiltersConfig.h | 4 | ||||
-rw-r--r-- | src/mpc-hc/InternalFiltersConfig_standard.h | 2 | ||||
-rw-r--r-- | src/mpc-hc/PPageInternalFilters.cpp | 2 | ||||
-rw-r--r-- | src/thirdparty/ffmpeg/Makefile | 3 | ||||
-rw-r--r-- | src/thirdparty/ffmpeg/config.h | 2 | ||||
-rw-r--r-- | src/thirdparty/ffmpeg/ffmpeg.vcxproj | 5 | ||||
-rw-r--r-- | src/thirdparty/ffmpeg/ffmpeg.vcxproj.filters | 15 | ||||
-rw-r--r-- | src/thirdparty/ffmpeg/libavcodec/allcodecs.c | 1 | ||||
-rw-r--r-- | src/thirdparty/ffmpeg/libavcodec/flac.c | 151 | ||||
-rw-r--r-- | src/thirdparty/ffmpeg/libavcodec/flac.h | 140 | ||||
-rw-r--r-- | src/thirdparty/ffmpeg/libavcodec/flacdata.c | 33 | ||||
-rw-r--r-- | src/thirdparty/ffmpeg/libavcodec/flacdata.h | 31 | ||||
-rw-r--r-- | src/thirdparty/ffmpeg/libavcodec/flacdec.c | 693 |
16 files changed, 1095 insertions, 191 deletions
diff --git a/src/filters/transform/MpaDecFilter/MpaDecFilter.cpp b/src/filters/transform/MpaDecFilter/MpaDecFilter.cpp index 544469e2d..56fe22ef4 100644 --- a/src/filters/transform/MpaDecFilter/MpaDecFilter.cpp +++ b/src/filters/transform/MpaDecFilter/MpaDecFilter.cpp @@ -48,8 +48,6 @@ void *__imp_time64 = _time64; #include <ffmpeg/libavcodec/avcodec.h>
#include <ffmpeg/libavutil/intreadwrite.h>
-#include <libflac/include/FLAC/stream_decoder.h>
-
#define INT8_PEAK 128
#define INT16_PEAK 32768
#define INT24_PEAK 8388608
@@ -116,20 +114,23 @@ static const FFMPEG_AUDIO_CODECS ffAudioCodecs[] = { #endif
#if INTERNAL_DECODER_REALAUDIO
// RealMedia Audio
- { &MEDIASUBTYPE_14_4, CODEC_ID_RA_144 },
- { &MEDIASUBTYPE_28_8, CODEC_ID_RA_288 },
- { &MEDIASUBTYPE_ATRC, CODEC_ID_ATRAC3 },
- { &MEDIASUBTYPE_COOK, CODEC_ID_COOK },
- { &MEDIASUBTYPE_SIPR, CODEC_ID_SIPR },
- { &MEDIASUBTYPE_RAAC, CODEC_ID_AAC },
- { &MEDIASUBTYPE_RACP, CODEC_ID_AAC },
+ { &MEDIASUBTYPE_14_4, CODEC_ID_RA_144 },
+ { &MEDIASUBTYPE_28_8, CODEC_ID_RA_288 },
+ { &MEDIASUBTYPE_ATRC, CODEC_ID_ATRAC3 },
+ { &MEDIASUBTYPE_COOK, CODEC_ID_COOK },
+ { &MEDIASUBTYPE_SIPR, CODEC_ID_SIPR },
+ { &MEDIASUBTYPE_RAAC, CODEC_ID_AAC },
+ { &MEDIASUBTYPE_RACP, CODEC_ID_AAC },
#endif
#if INTERNAL_DECODER_AC3
- { &MEDIASUBTYPE_DOLBY_DDPLUS, CODEC_ID_EAC3 },
- { &MEDIASUBTYPE_DOLBY_TRUEHD, CODEC_ID_TRUEHD },
- { &MEDIASUBTYPE_MLP, CODEC_ID_MLP },
+ { &MEDIASUBTYPE_DOLBY_DDPLUS, CODEC_ID_EAC3 },
+ { &MEDIASUBTYPE_DOLBY_TRUEHD, CODEC_ID_TRUEHD },
+ { &MEDIASUBTYPE_MLP, CODEC_ID_MLP },
+#endif
+#if INTERNAL_DECODER_FLAC
+ { &MEDIASUBTYPE_FLAC_FRAMED, CODEC_ID_FLAC },
#endif
- { &MEDIASUBTYPE_None, CODEC_ID_NONE },
+ { &MEDIASUBTYPE_None, CODEC_ID_NONE },
};
#endif
@@ -424,10 +425,6 @@ CMpaDecFilter::CMpaDecFilter(LPUNKNOWN lpunk, HRESULT* phr) m_nFFBufferSize = 0;
#endif
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
- memset (&m_flac, 0, sizeof(m_flac));
-#endif
-
#if defined(REGISTER_FILTER) || INTERNAL_DECODER_AC3
m_a52_state = NULL;
#endif
@@ -508,11 +505,6 @@ HRESULT CMpaDecFilter::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, d avcodec_flush_buffers (m_pAVCtx);
}
#endif
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
- if (m_flac.pDecoder) {
- FLAC__stream_decoder_flush((FLAC__StreamDecoder*) m_flac.pDecoder);
- }
-#endif
m_bResync = true;
@@ -633,11 +625,6 @@ HRESULT CMpaDecFilter::Receive(IMediaSample* pIn) hr = ProcessPS2ADPCM();
}
#endif
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
- else if (subtype == MEDIASUBTYPE_FLAC_FRAMED) {
- hr = ProcessFlac();
- }
-#endif
#if defined(REGISTER_FILTER) || INTERNAL_DECODER_PCM
else if (subtype == MEDIASUBTYPE_PCM_NONE ||
subtype == MEDIASUBTYPE_PCM_RAW) {
@@ -819,7 +806,7 @@ HRESULT CMpaDecFilter::ProcessHdmvLPCM(bool bAlignOldBuffer) // Blu ray LPCM CAtlArray<float> pBuff;
pBuff.SetCount(nFrames*nChannels); //nSamples
- float* pDataOut = pBuff.GetData();
+ float* pDataOut = pBuff.GetData();
switch (wfein->wBitsPerSample) {
case 16 :
@@ -1490,17 +1477,6 @@ HRESULT CMpaDecFilter::ProcessPS2ADPCM() }
#endif /* INTERNAL_DECODER_PS2AUDIO */
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
-HRESULT CMpaDecFilter::ProcessFlac()
-{
- WAVEFORMATEX* wfein = (WAVEFORMATEX*)m_pInput->CurrentMediaType().Format();
- UNREFERENCED_PARAMETER(wfein);
-
- FLAC__stream_decoder_process_single ((FLAC__StreamDecoder*) m_flac.pDecoder);
- return m_flac.hr;
-}
-#endif /* INTERNAL_DECODER_FLAC */
-
HRESULT CMpaDecFilter::GetDeliveryBuffer(IMediaSample** pSample, BYTE** pData)
{
HRESULT hr;
@@ -1929,9 +1905,6 @@ HRESULT CMpaDecFilter::StartStreaming() #endif
m_ps2_state.reset();
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
- FlacInitDecoder();
-#endif
m_fDiscontinuity = false;
@@ -1954,10 +1927,6 @@ HRESULT CMpaDecFilter::StopStreaming() }
#endif
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
- flac_stream_finish();
-#endif
-
#if defined(REGISTER_FILTER) || HAS_FFMPEG_AUDIO_DECODERS
ffmpeg_stream_finish();
#endif
@@ -2100,123 +2069,6 @@ CMpaDecInputPin::CMpaDecInputPin(CTransformFilter* pFilter, HRESULT* phr, LPWSTR {
}
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
-
-#pragma region Flac callback
-
-void CMpaDecFilter::FlacFillBuffer(BYTE buffer[], size_t *bytes)
-{
- UINT nSize = min (*bytes, m_buff.GetCount());
-
- if (nSize > 0) {
- memcpy_s (buffer, *bytes, m_buff.GetData(), nSize);
- memmove(m_buff.GetData(), m_buff.GetData() + nSize, m_buff.GetCount() - nSize);
- m_buff.SetCount(m_buff.GetCount() - nSize);
-
- }
- *bytes = nSize;
-}
-
-void CMpaDecFilter::FlacDeliverBuffer(unsigned blocksize, const __int32 * const buffer[])
-{
- WAVEFORMATEX* wfein = (WAVEFORMATEX*)m_pInput->CurrentMediaType().Format();
-
- WORD nChannels = wfein->nChannels;
- DWORD dwChannelMask = GetVorbisChannelMask(nChannels);
-
- //unsigned int nSamples = blocksize * nChannels;
-
- CAtlArray<float> pBuff;
- pBuff.SetCount(blocksize * nChannels);
- float* pDataOut = pBuff.GetData();
-
- switch (wfein->wBitsPerSample) {
- case 16 :
- for (unsigned int i = 0; i < blocksize; ++i) {
- for (unsigned int k = 0; k < nChannels; ++k) {
- FLAC__int16 nVal = (FLAC__int16)buffer[k][i];
- *pDataOut = (float)nVal / INT16_PEAK;
- pDataOut++;
- }
- }
- break;
- case 20 :
- case 24 :
- for (unsigned int i = 0; i < blocksize; ++i) {
- for (unsigned int k = 0; k < nChannels; ++k) {
- FLAC__int32 nVal = (FLAC__int32)buffer[k][i];
- *pDataOut = (float)nVal / INT24_PEAK;
- pDataOut++;
- }
- }
- break;
- }
-
- m_flac.hr = Deliver(pBuff, wfein->nSamplesPerSec, wfein->nChannels, dwChannelMask);
-}
-
-
-static FLAC__StreamDecoderReadStatus StreamDecoderRead(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
-{
- CMpaDecFilter* pThis = static_cast<CMpaDecFilter*> (client_data);
-
- pThis->FlacFillBuffer (buffer, bytes);
-
- return (*bytes == 0) ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-}
-
-static FLAC__StreamDecoderWriteStatus StreamDecoderWrite(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
- CMpaDecFilter* pThis = static_cast<CMpaDecFilter*> (client_data);
-
- pThis->FlacDeliverBuffer (frame->header.blocksize, buffer);
-
- return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
-}
-
-static void StreamDecoderError(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-}
-
-
-static void StreamDecoderMetadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-}
-
-void CMpaDecFilter::FlacInitDecoder()
-{
- if (!m_flac.pDecoder) {
- m_flac.pDecoder = FLAC__stream_decoder_new();
- if (m_flac.pDecoder) {
- FLAC__stream_decoder_init_stream ((FLAC__StreamDecoder*)m_flac.pDecoder,
- StreamDecoderRead,
- NULL,
- NULL,
- NULL,
- NULL,
- StreamDecoderWrite,
- StreamDecoderMetadata,
- StreamDecoderError,
- this);
- }
- } else {
- FLAC__stream_decoder_reset ((FLAC__StreamDecoder*)m_flac.pDecoder);
- }
-}
-
-
-void CMpaDecFilter::flac_stream_finish()
-{
- if (m_flac.pDecoder) {
- FLAC__stream_decoder_delete ((FLAC__StreamDecoder*)m_flac.pDecoder);
- m_flac.pDecoder = NULL;
- }
-}
-
-#pragma endregion
-
-#endif /* INTERNAL_DECODER_FLAC */
-
#if defined(REGISTER_FILTER) || HAS_FFMPEG_AUDIO_DECODERS
#pragma region FFmpeg decoder
diff --git a/src/filters/transform/MpaDecFilter/MpaDecFilter.h b/src/filters/transform/MpaDecFilter/MpaDecFilter.h index f0fb97276..1dca25af7 100644 --- a/src/filters/transform/MpaDecFilter/MpaDecFilter.h +++ b/src/filters/transform/MpaDecFilter/MpaDecFilter.h @@ -51,13 +51,6 @@ struct ps2_state_t { }
};
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
-struct flac_state_t {
- void* pDecoder;
- HRESULT hr;
-};
-#endif
-
struct AVCodec;
struct AVCodecContext;
struct AVFrame;
@@ -79,9 +72,7 @@ protected: dts_state_t* m_dts_state;
#endif
ps2_state_t m_ps2_state;
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
- flac_state_t m_flac;
-#endif
+
DolbyDigitalMode m_DolbyDigitalMode;
#if defined(REGISTER_FILTER) || HAS_FFMPEG_AUDIO_DECODERS
@@ -111,9 +102,6 @@ protected: HRESULT ProcessPS2PCM();
HRESULT ProcessPS2ADPCM();
#endif
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
- HRESULT ProcessFlac();
-#endif
#if defined(REGISTER_FILTER) || INTERNAL_DECODER_PCM
HRESULT ProcessPCMraw();
HRESULT ProcessPCMintBE();
@@ -129,11 +117,6 @@ protected: CMediaType CreateMediaType(MPCSampleFormat sf, DWORD nSamplesPerSec, WORD nChannels, DWORD dwChannelMask = 0);
CMediaType CreateMediaTypeSPDIF(DWORD nSamplesPerSec = 48000);
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
- void FlacInitDecoder();
- void flac_stream_finish();
-#endif
-
#if defined(REGISTER_FILTER) || HAS_FFMPEG_AUDIO_DECODERS
bool InitFFmpeg(enum CodecID nCodecId);
void ffmpeg_stream_finish();
@@ -204,11 +187,6 @@ public: STDMETHODIMP_(DolbyDigitalMode) GetDolbyDigitalMode();
STDMETHODIMP SaveSettings();
-
-#if defined(REGISTER_FILTER) || INTERNAL_DECODER_FLAC
- void FlacFillBuffer(BYTE buffer[], size_t *bytes);
- void FlacDeliverBuffer (unsigned blocksize, const __int32 * const buffer[]);
-#endif
};
class CMpaDecInputPin : public CDeCSSInputPin
diff --git a/src/mpc-hc/FilterEnum.h b/src/mpc-hc/FilterEnum.h index 853eabb2b..e10fc85eb 100644 --- a/src/mpc-hc/FilterEnum.h +++ b/src/mpc-hc/FilterEnum.h @@ -107,6 +107,8 @@ enum DECODER { #endif
#if INTERNAL_DECODER_DTS
TRA_DTS,
+#endif
+#if INTERNAL_DECODER_LPCM
TRA_LPCM,
#endif
#if INTERNAL_DECODER_AC3
diff --git a/src/mpc-hc/InternalFiltersConfig.h b/src/mpc-hc/InternalFiltersConfig.h index 9e6fb561b..4af4971cb 100644 --- a/src/mpc-hc/InternalFiltersConfig.h +++ b/src/mpc-hc/InternalFiltersConfig.h @@ -43,7 +43,7 @@ INTERNAL_SOURCEFILTER_REALMEDIA || INTERNAL_SOURCEFILTER_SHOUTCAST || INTERNAL_SOURCEFILTER_UDP || INTERNAL_SOURCEFILTER_AVI2AC3)
#define HAS_OTHER_AUDIO_DECODERS \
- (INTERNAL_DECODER_DTS || INTERNAL_DECODER_LPCM || INTERNAL_DECODER_PS2AUDIO || INTERNAL_DECODER_REALAUDIO || INTERNAL_DECODER_FLAC || INTERNAL_DECODER_PCM)
+ (INTERNAL_DECODER_DTS || INTERNAL_DECODER_LPCM || INTERNAL_DECODER_PS2AUDIO || INTERNAL_DECODER_REALAUDIO || INTERNAL_DECODER_PCM)
#define HAS_OTHER_VIDEO_DECODERS \
(INTERNAL_DECODER_MPEG1 || INTERNAL_DECODER_MPEG2 || INTERNAL_DECODER_REALVIDEO)
@@ -53,7 +53,7 @@ #define HAS_FFMPEG_AUDIO_DECODERS \
(INTERNAL_DECODER_AC3 || INTERNAL_DECODER_AAC || INTERNAL_DECODER_ALAC || INTERNAL_DECODER_ALS || INTERNAL_DECODER_MPEGAUDIO || \
- INTERNAL_DECODER_VORBIS || INTERNAL_DECODER_NELLYMOSER || INTERNAL_DECODER_AMR || INTERNAL_DECODER_ADPCM || INTERNAL_DECODER_REALAUDIO)
+ INTERNAL_DECODER_VORBIS || INTERNAL_DECODER_NELLYMOSER || INTERNAL_DECODER_AMR || INTERNAL_DECODER_ADPCM || INTERNAL_DECODER_REALAUDIO || INTERNAL_DECODER_FLAC)
#define HAS_FFMPEG_VIDEO_DECODERS \
(INTERNAL_DECODER_H264 || INTERNAL_DECODER_VC1 || INTERNAL_DECODER_FLV || INTERNAL_DECODER_VP356 || INTERNAL_DECODER_DIVX || INTERNAL_DECODER_XVID || INTERNAL_DECODER_WMV || \
diff --git a/src/mpc-hc/InternalFiltersConfig_standard.h b/src/mpc-hc/InternalFiltersConfig_standard.h index 74c1843ed..fea66a0af 100644 --- a/src/mpc-hc/InternalFiltersConfig_standard.h +++ b/src/mpc-hc/InternalFiltersConfig_standard.h @@ -46,7 +46,6 @@ #define INTERNAL_DECODER_LPCM 1
#define INTERNAL_DECODER_PS2AUDIO 1
#define INTERNAL_DECODER_REALAUDIO 1
-#define INTERNAL_DECODER_FLAC 1
#define INTERNAL_DECODER_PCM 1
// Internal audio decoders (FFmpeg)
@@ -59,6 +58,7 @@ #define INTERNAL_DECODER_NELLYMOSER 1
#define INTERNAL_DECODER_AMR 1
#define INTERNAL_DECODER_ADPCM 1
+#define INTERNAL_DECODER_FLAC 1
// Internal video decoders
#define INTERNAL_DECODER_MPEG1 1
diff --git a/src/mpc-hc/PPageInternalFilters.cpp b/src/mpc-hc/PPageInternalFilters.cpp index d42d98792..753f0209c 100644 --- a/src/mpc-hc/PPageInternalFilters.cpp +++ b/src/mpc-hc/PPageInternalFilters.cpp @@ -99,7 +99,7 @@ static filter_t s_filters[] = { {_T("Vorbis"), DECODER, TRA_VORBIS, IDS_TRA_FFMPEG, CreateInstance<CMpaDecFilter>},
#endif
#if INTERNAL_DECODER_FLAC
- {_T("FLAC"), DECODER, TRA_FLAC, 0, NULL /* TODO: CreateInstance<CMpaDecFilter>*/},
+ {_T("FLAC"), DECODER, TRA_FLAC, IDS_TRA_FFMPEG, CreateInstance<CMpaDecFilter>},
#endif
#if INTERNAL_DECODER_NELLYMOSER
{_T("Nellymoser"), DECODER, TRA_NELLY, IDS_TRA_FFMPEG, CreateInstance<CMpaDecFilter>},
diff --git a/src/thirdparty/ffmpeg/Makefile b/src/thirdparty/ffmpeg/Makefile index 40a84a108..51952033c 100644 --- a/src/thirdparty/ffmpeg/Makefile +++ b/src/thirdparty/ffmpeg/Makefile @@ -115,6 +115,9 @@ SRCS_C = \ libavcodec/faandct.c \
libavcodec/faanidct.c \
libavcodec/fft.c \
+ libavcodec/flac.c \
+ libavcodec/flacdata.c \
+ libavcodec/flacdec.c \
libavcodec/flvdec.c \
libavcodec/fmtconvert.c \
libavcodec/golomb.c \
diff --git a/src/thirdparty/ffmpeg/config.h b/src/thirdparty/ffmpeg/config.h index 2d9aafc00..2c3067424 100644 --- a/src/thirdparty/ffmpeg/config.h +++ b/src/thirdparty/ffmpeg/config.h @@ -353,7 +353,7 @@ Note: when adding a new codec, you have to: #define CONFIG_COOK_DECODER INTERNAL_DECODER_REALAUDIO
#define CONFIG_DCA_DECODER 0
#define CONFIG_EAC3_DECODER INTERNAL_DECODER_AC3
-#define CONFIG_FLAC_DECODER 0
+#define CONFIG_FLAC_DECODER INTERNAL_DECODER_FLAC
#define CONFIG_GSM_DECODER 0
#define CONFIG_GSM_MS_DECODER 0
#define CONFIG_IMC_DECODER 0
diff --git a/src/thirdparty/ffmpeg/ffmpeg.vcxproj b/src/thirdparty/ffmpeg/ffmpeg.vcxproj index a16979ebe..475dec4ff 100644 --- a/src/thirdparty/ffmpeg/ffmpeg.vcxproj +++ b/src/thirdparty/ffmpeg/ffmpeg.vcxproj @@ -182,6 +182,9 @@ <ClCompile Include="libavcodec\faandct.c" />
<ClCompile Include="libavcodec\faanidct.c" />
<ClCompile Include="libavcodec\fft.c" />
+ <ClCompile Include="libavcodec\flac.c" />
+ <ClCompile Include="libavcodec\flacdata.c" />
+ <ClCompile Include="libavcodec\flacdec.c" />
<ClCompile Include="libavcodec\flvdec.c" />
<ClCompile Include="libavcodec\fmtconvert.c" />
<ClCompile Include="libavcodec\golomb.c" />
@@ -428,6 +431,8 @@ <ClInclude Include="libavcodec\faanidct.h" />
<ClInclude Include="libavcodec\fft-internal.h" />
<ClInclude Include="libavcodec\fft.h" />
+ <ClInclude Include="libavcodec\flac.h" />
+ <ClInclude Include="libavcodec\flacdata.h" />
<ClInclude Include="libavcodec\flv.h" />
<ClInclude Include="libavcodec\fmtconvert.h" />
<ClInclude Include="libavcodec\get_bits.h" />
diff --git a/src/thirdparty/ffmpeg/ffmpeg.vcxproj.filters b/src/thirdparty/ffmpeg/ffmpeg.vcxproj.filters index 0b7abf086..382b7ca51 100644 --- a/src/thirdparty/ffmpeg/ffmpeg.vcxproj.filters +++ b/src/thirdparty/ffmpeg/ffmpeg.vcxproj.filters @@ -462,6 +462,15 @@ <ClCompile Include="libavcodec\fft.c">
<Filter>libavcodec</Filter>
</ClCompile>
+ <ClCompile Include="libavcodec\flac.c">
+ <Filter>libavcodec</Filter>
+ </ClCompile>
+ <ClCompile Include="libavcodec\flacdata.c">
+ <Filter>libavcodec</Filter>
+ </ClCompile>
+ <ClCompile Include="libavcodec\flacdec.c">
+ <Filter>libavcodec</Filter>
+ </ClCompile>
<ClCompile Include="libavcodec\flvdec.c">
<Filter>libavcodec</Filter>
</ClCompile>
@@ -1146,6 +1155,12 @@ <ClInclude Include="libavcodec\fft.h">
<Filter>libavcodec</Filter>
</ClInclude>
+ <ClInclude Include="libavcodec\flac.h">
+ <Filter>libavcodec</Filter>
+ </ClInclude>
+ <ClInclude Include="libavcodec\flacdata.h">
+ <Filter>libavcodec</Filter>
+ </ClInclude>
<ClInclude Include="libavcodec\fft-internal.h">
<Filter>libavcodec</Filter>
</ClInclude>
diff --git a/src/thirdparty/ffmpeg/libavcodec/allcodecs.c b/src/thirdparty/ffmpeg/libavcodec/allcodecs.c index c1ef7a3da..92c1a1079 100644 --- a/src/thirdparty/ffmpeg/libavcodec/allcodecs.c +++ b/src/thirdparty/ffmpeg/libavcodec/allcodecs.c @@ -89,6 +89,7 @@ void avcodec_register_all(void) REGISTER_DECODER (ATRAC3, atrac3); REGISTER_DECODER (COOK, cook); REGISTER_DECODER (EAC3, eac3); + REGISTER_DECODER (FLAC, flac); REGISTER_DECODER (MLP, mlp); REGISTER_DECODER (MP1FLOAT, mp1float); REGISTER_DECODER (MP2FLOAT, mp2float); diff --git a/src/thirdparty/ffmpeg/libavcodec/flac.c b/src/thirdparty/ffmpeg/libavcodec/flac.c new file mode 100644 index 000000000..484a44efb --- /dev/null +++ b/src/thirdparty/ffmpeg/libavcodec/flac.c @@ -0,0 +1,151 @@ +/* + * FLAC common code + * Copyright (c) 2009 Justin Ruggles + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/crc.h" +#include "flac.h" +#include "flacdata.h" + +static const int8_t sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 }; + +static int64_t get_utf8(GetBitContext *gb) +{ + int64_t val; + GET_UTF8(val, get_bits(gb, 8), return -1;) + return val; +} + +int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, + FLACFrameInfo *fi, int log_level_offset) +{ + int bs_code, sr_code, bps_code; + + /* frame sync code */ + if ((get_bits(gb, 15) & 0x7FFF) != 0x7FFC) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, "invalid sync code\n"); + return -1; + } + + /* variable block size stream code */ + fi->is_var_size = get_bits1(gb); + + /* block size and sample rate codes */ + bs_code = get_bits(gb, 4); + sr_code = get_bits(gb, 4); + + /* channels and decorrelation */ + fi->ch_mode = get_bits(gb, 4); + if (fi->ch_mode < FLAC_MAX_CHANNELS) { + fi->channels = fi->ch_mode + 1; + fi->ch_mode = FLAC_CHMODE_INDEPENDENT; + } else if (fi->ch_mode <= FLAC_CHMODE_MID_SIDE) { + fi->channels = 2; + } else { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "invalid channel mode: %d\n", fi->ch_mode); + return -1; + } + + /* bits per sample */ + bps_code = get_bits(gb, 3); + if (bps_code == 3 || bps_code == 7) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "invalid sample size code (%d)\n", + bps_code); + return -1; + } + fi->bps = sample_size_table[bps_code]; + + /* reserved bit */ + if (get_bits1(gb)) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "broken stream, invalid padding\n"); + return -1; + } + + /* sample or frame count */ + fi->frame_or_sample_num = get_utf8(gb); + if (fi->frame_or_sample_num < 0) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "sample/frame number invalid; utf8 fscked\n"); + return -1; + } + + /* blocksize */ + if (bs_code == 0) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "reserved blocksize code: 0\n"); + return -1; + } else if (bs_code == 6) { + fi->blocksize = get_bits(gb, 8) + 1; + } else if (bs_code == 7) { + fi->blocksize = get_bits(gb, 16) + 1; + } else { + fi->blocksize = ff_flac_blocksize_table[bs_code]; + } + + /* sample rate */ + if (sr_code < 12) { + fi->samplerate = ff_flac_sample_rate_table[sr_code]; + } else if (sr_code == 12) { + fi->samplerate = get_bits(gb, 8) * 1000; + } else if (sr_code == 13) { + fi->samplerate = get_bits(gb, 16); + } else if (sr_code == 14) { + fi->samplerate = get_bits(gb, 16) * 10; + } else { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "illegal sample rate code %d\n", + sr_code); + return -1; + } + + /* header CRC-8 check */ + skip_bits(gb, 8); + if (av_crc(av_crc_get_table(AV_CRC_8_ATM), 0, gb->buffer, + get_bits_count(gb)/8)) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "header crc mismatch\n"); + return -1; + } + + return 0; +} + +int ff_flac_get_max_frame_size(int blocksize, int ch, int bps) +{ + /* Technically, there is no limit to FLAC frame size, but an encoder + should not write a frame that is larger than if verbatim encoding mode + were to be used. */ + + int count; + + count = 16; /* frame header */ + count += ch * ((7+bps+7)/8); /* subframe headers */ + if (ch == 2) { + /* for stereo, need to account for using decorrelation */ + count += (( 2*bps+1) * blocksize + 7) / 8; + } else { + count += ( ch*bps * blocksize + 7) / 8; + } + count += 2; /* frame footer */ + + return count; +} diff --git a/src/thirdparty/ffmpeg/libavcodec/flac.h b/src/thirdparty/ffmpeg/libavcodec/flac.h new file mode 100644 index 000000000..65965af6a --- /dev/null +++ b/src/thirdparty/ffmpeg/libavcodec/flac.h @@ -0,0 +1,140 @@ +/* + * FLAC (Free Lossless Audio Codec) decoder/demuxer common functions + * Copyright (c) 2008 Justin Ruggles + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * FLAC (Free Lossless Audio Codec) decoder/demuxer common functions + */ + +#ifndef AVCODEC_FLAC_H +#define AVCODEC_FLAC_H + +#include "avcodec.h" +#include "get_bits.h" + +#define FLAC_STREAMINFO_SIZE 34 +#define FLAC_MAX_CHANNELS 8 +#define FLAC_MIN_BLOCKSIZE 16 +#define FLAC_MAX_BLOCKSIZE 65535 +#define FLAC_MIN_FRAME_SIZE 11 + +enum { + FLAC_CHMODE_INDEPENDENT = 0, + FLAC_CHMODE_LEFT_SIDE = 8, + FLAC_CHMODE_RIGHT_SIDE = 9, + FLAC_CHMODE_MID_SIDE = 10, +}; + +enum { + FLAC_METADATA_TYPE_STREAMINFO = 0, + FLAC_METADATA_TYPE_PADDING, + FLAC_METADATA_TYPE_APPLICATION, + FLAC_METADATA_TYPE_SEEKTABLE, + FLAC_METADATA_TYPE_VORBIS_COMMENT, + FLAC_METADATA_TYPE_CUESHEET, + FLAC_METADATA_TYPE_PICTURE, + FLAC_METADATA_TYPE_INVALID = 127 +}; + +enum FLACExtradataFormat { + FLAC_EXTRADATA_FORMAT_STREAMINFO = 0, + FLAC_EXTRADATA_FORMAT_FULL_HEADER = 1 +}; + +#define FLACCOMMONINFO \ + int samplerate; /**< sample rate */\ + int channels; /**< number of channels */\ + int bps; /**< bits-per-sample */\ + +/** + * Data needed from the Streaminfo header for use by the raw FLAC demuxer + * and/or the FLAC decoder. + */ +#define FLACSTREAMINFO \ + FLACCOMMONINFO \ + int max_blocksize; /**< maximum block size, in samples */\ + int max_framesize; /**< maximum frame size, in bytes */\ + int64_t samples; /**< total number of samples */\ + +typedef struct FLACStreaminfo { + FLACSTREAMINFO +} FLACStreaminfo; + +typedef struct FLACFrameInfo { + FLACCOMMONINFO + int blocksize; /**< block size of the frame */ + int ch_mode; /**< channel decorrelation mode */ + int64_t frame_or_sample_num; /**< frame number or sample number */ + int is_var_size; /**< specifies if the stream uses variable + block sizes or a fixed block size; + also determines the meaning of + frame_or_sample_num */ +} FLACFrameInfo; + +/** + * Parse the Streaminfo metadata block + * @param[out] avctx codec context to set basic stream parameters + * @param[out] s where parsed information is stored + * @param[in] buffer pointer to start of 34-byte streaminfo data + */ +void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, + const uint8_t *buffer); + +/** + * Validate the FLAC extradata. + * @param[in] avctx codec context containing the extradata. + * @param[out] format extradata format. + * @param[out] streaminfo_start pointer to start of 34-byte STREAMINFO data. + * @return 1 if valid, 0 if not valid. + */ +int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, + enum FLACExtradataFormat *format, + uint8_t **streaminfo_start); + +/** + * Parse the metadata block parameters from the header. + * @param[in] block_header header data, at least 4 bytes + * @param[out] last indicator for last metadata block + * @param[out] type metadata block type + * @param[out] size metadata block size + */ +void avpriv_flac_parse_block_header(const uint8_t *block_header, + int *last, int *type, int *size); + +/** + * Calculate an estimate for the maximum frame size based on verbatim mode. + * @param blocksize block size, in samples + * @param ch number of channels + * @param bps bits-per-sample + */ +int ff_flac_get_max_frame_size(int blocksize, int ch, int bps); + +/** + * Validate and decode a frame header. + * @param avctx AVCodecContext to use as av_log() context + * @param gb GetBitContext from which to read frame header + * @param[out] fi frame information + * @param log_level_offset log level offset. can be used to silence error messages. + * @return non-zero on error, 0 if ok + */ +int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, + FLACFrameInfo *fi, int log_level_offset); +#endif /* AVCODEC_FLAC_H */ diff --git a/src/thirdparty/ffmpeg/libavcodec/flacdata.c b/src/thirdparty/ffmpeg/libavcodec/flacdata.c new file mode 100644 index 000000000..6fcbe3955 --- /dev/null +++ b/src/thirdparty/ffmpeg/libavcodec/flacdata.c @@ -0,0 +1,33 @@ +/* + * FLAC data + * Copyright (c) 2003 Alex Beregszaszi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "internal.h" + +const int ff_flac_sample_rate_table[16] = +{ 0, + 88200, 176400, 192000, + 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000, + 0, 0, 0, 0 }; + +const int16_t ff_flac_blocksize_table[16] = { + 0, 192, 576<<0, 576<<1, 576<<2, 576<<3, 0, 0, +256<<0, 256<<1, 256<<2, 256<<3, 256<<4, 256<<5, 256<<6, 256<<7 +}; diff --git a/src/thirdparty/ffmpeg/libavcodec/flacdata.h b/src/thirdparty/ffmpeg/libavcodec/flacdata.h new file mode 100644 index 000000000..96a50b918 --- /dev/null +++ b/src/thirdparty/ffmpeg/libavcodec/flacdata.h @@ -0,0 +1,31 @@ +/* + * FLAC data header + * Copyright (c) 2003 Alex Beregszaszi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_FLACDATA_H +#define AVCODEC_FLACDATA_H + +#include "internal.h" + +extern const int ff_flac_sample_rate_table[16]; + +extern const int16_t ff_flac_blocksize_table[16]; + +#endif /* AVCODEC_FLACDATA_H */ diff --git a/src/thirdparty/ffmpeg/libavcodec/flacdec.c b/src/thirdparty/ffmpeg/libavcodec/flacdec.c new file mode 100644 index 000000000..82c4e807d --- /dev/null +++ b/src/thirdparty/ffmpeg/libavcodec/flacdec.c @@ -0,0 +1,693 @@ +/* + * FLAC (Free Lossless Audio Codec) decoder + * Copyright (c) 2003 Alex Beregszaszi + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * FLAC (Free Lossless Audio Codec) decoder + * @author Alex Beregszaszi + * @see http://flac.sourceforge.net/ + * + * This decoder can be used in 1 of 2 ways: Either raw FLAC data can be fed + * through, starting from the initial 'fLaC' signature; or by passing the + * 34-byte streaminfo structure through avctx->extradata[_size] followed + * by data starting with the 0xFFF8 marker. + */ + +#include <limits.h> + +#include "libavutil/audioconvert.h" +#include "libavutil/crc.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "bytestream.h" +#include "golomb.h" +#include "flac.h" +#include "flacdata.h" + +#undef NDEBUG +#include <assert.h> + +typedef struct FLACContext { + FLACSTREAMINFO + + AVCodecContext *avctx; ///< parent AVCodecContext + AVFrame frame; + GetBitContext gb; ///< GetBitContext initialized to start at the current frame + + int blocksize; ///< number of samples in the current frame + int curr_bps; ///< bps for current subframe, adjusted for channel correlation and wasted bits + int sample_shift; ///< shift required to make output samples 16-bit or 32-bit + int is32; ///< flag to indicate if output should be 32-bit instead of 16-bit + int ch_mode; ///< channel decorrelation type in the current frame + int got_streaminfo; ///< indicates if the STREAMINFO has been read + + int32_t *decoded[FLAC_MAX_CHANNELS]; ///< decoded samples +} FLACContext; + +static const int64_t flac_channel_layouts[6] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_QUAD, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_5POINT1 +}; + +static void allocate_buffers(FLACContext *s); + +int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, + enum FLACExtradataFormat *format, + uint8_t **streaminfo_start) +{ + if (!avctx->extradata || avctx->extradata_size < FLAC_STREAMINFO_SIZE) { + av_log(avctx, AV_LOG_ERROR, "extradata NULL or too small.\n"); + return 0; + } + if (AV_RL32(avctx->extradata) != MKTAG('f','L','a','C')) { + /* extradata contains STREAMINFO only */ + if (avctx->extradata_size != FLAC_STREAMINFO_SIZE) { + av_log(avctx, AV_LOG_WARNING, "extradata contains %d bytes too many.\n", + FLAC_STREAMINFO_SIZE-avctx->extradata_size); + } + *format = FLAC_EXTRADATA_FORMAT_STREAMINFO; + *streaminfo_start = avctx->extradata; + } else { + if (avctx->extradata_size < 8+FLAC_STREAMINFO_SIZE) { + av_log(avctx, AV_LOG_ERROR, "extradata too small.\n"); + return 0; + } + *format = FLAC_EXTRADATA_FORMAT_FULL_HEADER; + *streaminfo_start = &avctx->extradata[8]; + } + return 1; +} + +static av_cold int flac_decode_init(AVCodecContext *avctx) +{ + enum FLACExtradataFormat format; + uint8_t *streaminfo; + FLACContext *s = avctx->priv_data; + s->avctx = avctx; + + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + /* for now, the raw FLAC header is allowed to be passed to the decoder as + frame data instead of extradata. */ + if (!avctx->extradata) + return 0; + + if (!avpriv_flac_is_extradata_valid(avctx, &format, &streaminfo)) + return -1; + + /* initialize based on the demuxer-supplied streamdata header */ + avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo); + if (s->bps > 16) + avctx->sample_fmt = AV_SAMPLE_FMT_S32; + else + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + allocate_buffers(s); + s->got_streaminfo = 1; + + avcodec_get_frame_defaults(&s->frame); + avctx->coded_frame = &s->frame; + + if (avctx->channels <= FF_ARRAY_ELEMS(flac_channel_layouts)) + avctx->channel_layout = flac_channel_layouts[avctx->channels - 1]; + + return 0; +} + +static void dump_headers(AVCodecContext *avctx, FLACStreaminfo *s) +{ + av_log(avctx, AV_LOG_DEBUG, " Max Blocksize: %d\n", s->max_blocksize); + av_log(avctx, AV_LOG_DEBUG, " Max Framesize: %d\n", s->max_framesize); + av_log(avctx, AV_LOG_DEBUG, " Samplerate: %d\n", s->samplerate); + av_log(avctx, AV_LOG_DEBUG, " Channels: %d\n", s->channels); + av_log(avctx, AV_LOG_DEBUG, " Bits: %d\n", s->bps); +} + +static void allocate_buffers(FLACContext *s) +{ + int i; + + assert(s->max_blocksize); + + for (i = 0; i < s->channels; i++) { + s->decoded[i] = av_realloc(s->decoded[i], + sizeof(int32_t)*s->max_blocksize); + } +} + +void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, + const uint8_t *buffer) +{ + GetBitContext gb; + init_get_bits(&gb, buffer, FLAC_STREAMINFO_SIZE*8); + + skip_bits(&gb, 16); /* skip min blocksize */ + s->max_blocksize = get_bits(&gb, 16); + if (s->max_blocksize < FLAC_MIN_BLOCKSIZE) { + av_log(avctx, AV_LOG_WARNING, "invalid max blocksize: %d\n", + s->max_blocksize); + s->max_blocksize = 16; + } + + skip_bits(&gb, 24); /* skip min frame size */ + s->max_framesize = get_bits_long(&gb, 24); + + s->samplerate = get_bits_long(&gb, 20); + s->channels = get_bits(&gb, 3) + 1; + s->bps = get_bits(&gb, 5) + 1; + + avctx->channels = s->channels; + avctx->sample_rate = s->samplerate; + avctx->bits_per_raw_sample = s->bps; + + s->samples = get_bits_long(&gb, 32) << 4; + s->samples |= get_bits(&gb, 4); + + skip_bits_long(&gb, 64); /* md5 sum */ + skip_bits_long(&gb, 64); /* md5 sum */ + + dump_headers(avctx, s); +} + +void avpriv_flac_parse_block_header(const uint8_t *block_header, + int *last, int *type, int *size) +{ + int tmp = bytestream_get_byte(&block_header); + if (last) + *last = tmp & 0x80; + if (type) + *type = tmp & 0x7F; + if (size) + *size = bytestream_get_be24(&block_header); +} + +/** + * Parse the STREAMINFO from an inline header. + * @param s the flac decoding context + * @param buf input buffer, starting with the "fLaC" marker + * @param buf_size buffer size + * @return non-zero if metadata is invalid + */ +static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size) +{ + int metadata_type, metadata_size; + + if (buf_size < FLAC_STREAMINFO_SIZE+8) { + /* need more data */ + return 0; + } + avpriv_flac_parse_block_header(&buf[4], NULL, &metadata_type, &metadata_size); + if (metadata_type != FLAC_METADATA_TYPE_STREAMINFO || + metadata_size != FLAC_STREAMINFO_SIZE) { + return AVERROR_INVALIDDATA; + } + avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]); + allocate_buffers(s); + s->got_streaminfo = 1; + + return 0; +} + +/** + * Determine the size of an inline header. + * @param buf input buffer, starting with the "fLaC" marker + * @param buf_size buffer size + * @return number of bytes in the header, or 0 if more data is needed + */ +static int get_metadata_size(const uint8_t *buf, int buf_size) +{ + int metadata_last, metadata_size; + const uint8_t *buf_end = buf + buf_size; + + buf += 4; + do { + if (buf_end - buf < 4) + return 0; + avpriv_flac_parse_block_header(buf, &metadata_last, NULL, &metadata_size); + buf += 4; + if (buf_end - buf < metadata_size) { + /* need more data in order to read the complete header */ + return 0; + } + buf += metadata_size; + } while (!metadata_last); + + return buf_size - (buf_end - buf); +} + +static int decode_residuals(FLACContext *s, int channel, int pred_order) +{ + int i, tmp, partition, method_type, rice_order; + int sample = 0, samples; + + method_type = get_bits(&s->gb, 2); + if (method_type > 1) { + av_log(s->avctx, AV_LOG_ERROR, "illegal residual coding method %d\n", + method_type); + return -1; + } + + rice_order = get_bits(&s->gb, 4); + + samples= s->blocksize >> rice_order; + if (pred_order > samples) { + av_log(s->avctx, AV_LOG_ERROR, "invalid predictor order: %i > %i\n", + pred_order, samples); + return -1; + } + + sample= + i= pred_order; + for (partition = 0; partition < (1 << rice_order); partition++) { + tmp = get_bits(&s->gb, method_type == 0 ? 4 : 5); + if (tmp == (method_type == 0 ? 15 : 31)) { + tmp = get_bits(&s->gb, 5); + for (; i < samples; i++, sample++) + s->decoded[channel][sample] = get_sbits_long(&s->gb, tmp); + } else { + for (; i < samples; i++, sample++) { + s->decoded[channel][sample] = get_sr_golomb_flac(&s->gb, tmp, INT_MAX, 0); + } + } + i= 0; + } + + return 0; +} + +static int decode_subframe_fixed(FLACContext *s, int channel, int pred_order) +{ + const int blocksize = s->blocksize; + int32_t *decoded = s->decoded[channel]; + int a, b, c, d, i; + + /* warm up samples */ + for (i = 0; i < pred_order; i++) { + decoded[i] = get_sbits_long(&s->gb, s->curr_bps); + } + + if (decode_residuals(s, channel, pred_order) < 0) + return -1; + + if (pred_order > 0) + a = decoded[pred_order-1]; + if (pred_order > 1) + b = a - decoded[pred_order-2]; + if (pred_order > 2) + c = b - decoded[pred_order-2] + decoded[pred_order-3]; + if (pred_order > 3) + d = c - decoded[pred_order-2] + 2*decoded[pred_order-3] - decoded[pred_order-4]; + + switch (pred_order) { + case 0: + break; + case 1: + for (i = pred_order; i < blocksize; i++) + decoded[i] = a += decoded[i]; + break; + case 2: + for (i = pred_order; i < blocksize; i++) + decoded[i] = a += b += decoded[i]; + break; + case 3: + for (i = pred_order; i < blocksize; i++) + decoded[i] = a += b += c += decoded[i]; + break; + case 4: + for (i = pred_order; i < blocksize; i++) + decoded[i] = a += b += c += d += decoded[i]; + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "illegal pred order %d\n", pred_order); + return -1; + } + + return 0; +} + +static int decode_subframe_lpc(FLACContext *s, int channel, int pred_order) +{ + int i, j; + int coeff_prec, qlevel; + int coeffs[32]; + int32_t *decoded = s->decoded[channel]; + + /* warm up samples */ + for (i = 0; i < pred_order; i++) { + decoded[i] = get_sbits_long(&s->gb, s->curr_bps); + } + + coeff_prec = get_bits(&s->gb, 4) + 1; + if (coeff_prec == 16) { + av_log(s->avctx, AV_LOG_ERROR, "invalid coeff precision\n"); + return -1; + } + qlevel = get_sbits(&s->gb, 5); + if (qlevel < 0) { + av_log(s->avctx, AV_LOG_ERROR, "qlevel %d not supported, maybe buggy stream\n", + qlevel); + return -1; + } + + for (i = 0; i < pred_order; i++) { + coeffs[i] = get_sbits(&s->gb, coeff_prec); + } + + if (decode_residuals(s, channel, pred_order) < 0) + return -1; + + if (s->bps > 16) { + int64_t sum; + for (i = pred_order; i < s->blocksize; i++) { + sum = 0; + for (j = 0; j < pred_order; j++) + sum += (int64_t)coeffs[j] * decoded[i-j-1]; + decoded[i] += sum >> qlevel; + } + } else { + for (i = pred_order; i < s->blocksize-1; i += 2) { + int c; + int d = decoded[i-pred_order]; + int s0 = 0, s1 = 0; + for (j = pred_order-1; j > 0; j--) { + c = coeffs[j]; + s0 += c*d; + d = decoded[i-j]; + s1 += c*d; + } + c = coeffs[0]; + s0 += c*d; + d = decoded[i] += s0 >> qlevel; + s1 += c*d; + decoded[i+1] += s1 >> qlevel; + } + if (i < s->blocksize) { + int sum = 0; + for (j = 0; j < pred_order; j++) + sum += coeffs[j] * decoded[i-j-1]; + decoded[i] += sum >> qlevel; + } + } + + return 0; +} + +static inline int decode_subframe(FLACContext *s, int channel) +{ + int type, wasted = 0; + int i, tmp; + + s->curr_bps = s->bps; + if (channel == 0) { + if (s->ch_mode == FLAC_CHMODE_RIGHT_SIDE) + s->curr_bps++; + } else { + if (s->ch_mode == FLAC_CHMODE_LEFT_SIDE || s->ch_mode == FLAC_CHMODE_MID_SIDE) + s->curr_bps++; + } + + if (get_bits1(&s->gb)) { + av_log(s->avctx, AV_LOG_ERROR, "invalid subframe padding\n"); + return -1; + } + type = get_bits(&s->gb, 6); + + if (get_bits1(&s->gb)) { + int left = get_bits_left(&s->gb); + wasted = 1; + if ( left < 0 || + (left < s->curr_bps && !show_bits_long(&s->gb, left)) || + !show_bits_long(&s->gb, s->curr_bps)) { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid number of wasted bits > available bits (%d) - left=%d\n", + s->curr_bps, left); + return AVERROR_INVALIDDATA; + } + while (!get_bits1(&s->gb)) + wasted++; + s->curr_bps -= wasted; + } + if (s->curr_bps > 32) { + av_log_missing_feature(s->avctx, "decorrelated bit depth > 32", 0); + return -1; + } + +//FIXME use av_log2 for types + if (type == 0) { + tmp = get_sbits_long(&s->gb, s->curr_bps); + for (i = 0; i < s->blocksize; i++) + s->decoded[channel][i] = tmp; + } else if (type == 1) { + for (i = 0; i < s->blocksize; i++) + s->decoded[channel][i] = get_sbits_long(&s->gb, s->curr_bps); + } else if ((type >= 8) && (type <= 12)) { + if (decode_subframe_fixed(s, channel, type & ~0x8) < 0) + return -1; + } else if (type >= 32) { + if (decode_subframe_lpc(s, channel, (type & ~0x20)+1) < 0) + return -1; + } else { + av_log(s->avctx, AV_LOG_ERROR, "invalid coding type\n"); + return -1; + } + + if (wasted) { + int i; + for (i = 0; i < s->blocksize; i++) + s->decoded[channel][i] <<= wasted; + } + + return 0; +} + +static int decode_frame(FLACContext *s) +{ + int i; + GetBitContext *gb = &s->gb; + FLACFrameInfo fi; + + if (ff_flac_decode_frame_header(s->avctx, gb, &fi, 0)) { + av_log(s->avctx, AV_LOG_ERROR, "invalid frame header\n"); + return -1; + } + + if (s->channels && fi.channels != s->channels) { + av_log(s->avctx, AV_LOG_ERROR, "switching channel layout mid-stream " + "is not supported\n"); + return -1; + } + s->channels = s->avctx->channels = fi.channels; + s->ch_mode = fi.ch_mode; + + if (!s->bps && !fi.bps) { + av_log(s->avctx, AV_LOG_ERROR, "bps not found in STREAMINFO or frame header\n"); + return -1; + } + if (!fi.bps) { + fi.bps = s->bps; + } else if (s->bps && fi.bps != s->bps) { + av_log(s->avctx, AV_LOG_ERROR, "switching bps mid-stream is not " + "supported\n"); + return -1; + } + s->bps = s->avctx->bits_per_raw_sample = fi.bps; + + if (s->bps > 16) { + s->avctx->sample_fmt = AV_SAMPLE_FMT_S32; + s->sample_shift = 32 - s->bps; + s->is32 = 1; + } else { + s->avctx->sample_fmt = AV_SAMPLE_FMT_S16; + s->sample_shift = 16 - s->bps; + s->is32 = 0; + } + + if (!s->max_blocksize) + s->max_blocksize = FLAC_MAX_BLOCKSIZE; + if (fi.blocksize > s->max_blocksize) { + av_log(s->avctx, AV_LOG_ERROR, "blocksize %d > %d\n", fi.blocksize, + s->max_blocksize); + return -1; + } + s->blocksize = fi.blocksize; + + if (!s->samplerate && !fi.samplerate) { + av_log(s->avctx, AV_LOG_ERROR, "sample rate not found in STREAMINFO" + " or frame header\n"); + return -1; + } + if (fi.samplerate == 0) { + fi.samplerate = s->samplerate; + } else if (s->samplerate && fi.samplerate != s->samplerate) { + av_log(s->avctx, AV_LOG_WARNING, "sample rate changed from %d to %d\n", + s->samplerate, fi.samplerate); + } + s->samplerate = s->avctx->sample_rate = fi.samplerate; + + if (!s->got_streaminfo) { + allocate_buffers(s); + s->got_streaminfo = 1; + dump_headers(s->avctx, (FLACStreaminfo *)s); + } + +// dump_headers(s->avctx, (FLACStreaminfo *)s); + + /* subframes */ + for (i = 0; i < s->channels; i++) { + if (decode_subframe(s, i) < 0) + return -1; + } + + align_get_bits(gb); + + /* frame footer */ + skip_bits(gb, 16); /* data crc */ + + return 0; +} + +static int flac_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + FLACContext *s = avctx->priv_data; + int i, j = 0, bytes_read = 0; + int16_t *samples_16; + int32_t *samples_32; + int ret; + + *got_frame_ptr = 0; + + if (s->max_framesize == 0) { + s->max_framesize = + ff_flac_get_max_frame_size(s->max_blocksize ? s->max_blocksize : FLAC_MAX_BLOCKSIZE, + FLAC_MAX_CHANNELS, 32); + } + + /* check that there is at least the smallest decodable amount of data. + this amount corresponds to the smallest valid FLAC frame possible. + FF F8 69 02 00 00 9A 00 00 34 46 */ + if (buf_size < FLAC_MIN_FRAME_SIZE) + return buf_size; + + /* check for inline header */ + if (AV_RB32(buf) == MKBETAG('f','L','a','C')) { + if (!s->got_streaminfo && parse_streaminfo(s, buf, buf_size)) { + av_log(s->avctx, AV_LOG_ERROR, "invalid header\n"); + return -1; + } + return get_metadata_size(buf, buf_size); + } + + /* decode frame */ + init_get_bits(&s->gb, buf, buf_size*8); + if (decode_frame(s) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "decode_frame() failed\n"); + return -1; + } + bytes_read = (get_bits_count(&s->gb)+7)/8; + + /* get output buffer */ + s->frame.nb_samples = s->blocksize; + if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + samples_16 = (int16_t *)s->frame.data[0]; + samples_32 = (int32_t *)s->frame.data[0]; + +#define DECORRELATE(left, right)\ + assert(s->channels == 2);\ + for (i = 0; i < s->blocksize; i++) {\ + int a= s->decoded[0][i];\ + int b= s->decoded[1][i];\ + if (s->is32) {\ + *samples_32++ = (left) << s->sample_shift;\ + *samples_32++ = (right) << s->sample_shift;\ + } else {\ + *samples_16++ = (left) << s->sample_shift;\ + *samples_16++ = (right) << s->sample_shift;\ + }\ + }\ + break; + + switch (s->ch_mode) { + case FLAC_CHMODE_INDEPENDENT: + for (j = 0; j < s->blocksize; j++) { + for (i = 0; i < s->channels; i++) { + if (s->is32) + *samples_32++ = s->decoded[i][j] << s->sample_shift; + else + *samples_16++ = s->decoded[i][j] << s->sample_shift; + } + } + break; + case FLAC_CHMODE_LEFT_SIDE: + DECORRELATE(a,a-b) + case FLAC_CHMODE_RIGHT_SIDE: + DECORRELATE(a+b,b) + case FLAC_CHMODE_MID_SIDE: + DECORRELATE( (a-=b>>1) + b, a) + } + + if (bytes_read > buf_size) { + av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", bytes_read - buf_size); + return -1; + } + if (bytes_read < buf_size) { + av_log(s->avctx, AV_LOG_DEBUG, "underread: %d orig size: %d\n", + buf_size - bytes_read, buf_size); + } + + *got_frame_ptr = 1; + *(AVFrame *)data = s->frame; + + return bytes_read; +} + +static av_cold int flac_decode_close(AVCodecContext *avctx) +{ + FLACContext *s = avctx->priv_data; + int i; + + for (i = 0; i < s->channels; i++) { + av_freep(&s->decoded[i]); + } + + return 0; +} + +AVCodec ff_flac_decoder = { + .name = "flac", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_FLAC, + .priv_data_size = sizeof(FLACContext), + .init = flac_decode_init, + .close = flac_decode_close, + .decode = flac_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), +}; |