Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ffmpeg] Convert from av_audio_convert API to the swresample one. #882

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 0 additions & 40 deletions lib/DllAvCodec.h
Expand Up @@ -58,20 +58,8 @@ extern "C" {
#include <ffmpeg/avformat.h>
#endif
#endif

/* From non-public audioconvert.h */
struct AVAudioConvert;
typedef struct AVAudioConvert AVAudioConvert;
AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels,
enum AVSampleFormat in_fmt, int in_channels,
const float *matrix, int flags);
void av_audio_convert_free(AVAudioConvert *ctx);
int av_audio_convert(AVAudioConvert *ctx,
void * const out[6], const int out_stride[6],
const void * const in[6], const int in_stride[6], int len);
#else
#include "libavcodec/avcodec.h"
#include "libavcodec/audioconvert.h"
#endif
}

Expand Down Expand Up @@ -115,13 +103,6 @@ class DllAvCodecInterface
virtual int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic)=0;
virtual void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic)=0;
virtual AVCodec *av_codec_next(AVCodec *c)=0;
virtual AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels,
enum AVSampleFormat in_fmt , int in_channels,
const float *matrix , int flags)=0;
virtual void av_audio_convert_free(AVAudioConvert *ctx)=0;
virtual int av_audio_convert(AVAudioConvert *ctx,
void * const out[6], const int out_stride[6],
const void * const in[6], const int in_stride[6], int len)=0;
virtual int av_dup_packet(AVPacket *pkt)=0;
virtual void av_init_packet(AVPacket *pkt)=0;
};
Expand Down Expand Up @@ -189,17 +170,6 @@ class DllAvCodec : public DllDynamic, DllAvCodecInterface
virtual void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic) { ::avcodec_default_release_buffer(s, pic); }
virtual enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat *fmt) { return ::avcodec_default_get_format(s, fmt); }
virtual AVCodec *av_codec_next(AVCodec *c) { return ::av_codec_next(c); }
virtual AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels,
enum AVSampleFormat in_fmt , int in_channels,
const float *matrix , int flags)
{ return ::av_audio_convert_alloc(out_fmt, out_channels, in_fmt, in_channels, matrix, flags); }
virtual void av_audio_convert_free(AVAudioConvert *ctx)
{ ::av_audio_convert_free(ctx); }

virtual int av_audio_convert(AVAudioConvert *ctx,
void * const out[6], const int out_stride[6],
const void * const in[6], const int in_stride[6], int len)
{ return ::av_audio_convert(ctx, out, out_stride, in, in_stride, len); }

virtual int av_dup_packet(AVPacket *pkt) { return ::av_dup_packet(pkt); }
virtual void av_init_packet(AVPacket *pkt) { return ::av_init_packet(pkt); }
Expand Down Expand Up @@ -251,13 +221,6 @@ class DllAvCodec : public DllDynamic, DllAvCodecInterface
DEFINE_METHOD2(enum PixelFormat, avcodec_default_get_format, (struct AVCodecContext *p1, const enum PixelFormat *p2))

DEFINE_METHOD1(AVCodec*, av_codec_next, (AVCodec *p1))
DEFINE_METHOD6(AVAudioConvert*, av_audio_convert_alloc, (enum AVSampleFormat p1, int p2,
enum AVSampleFormat p3, int p4,
const float *p5, int p6))
DEFINE_METHOD1(void, av_audio_convert_free, (AVAudioConvert *p1));
DEFINE_METHOD6(int, av_audio_convert, (AVAudioConvert *p1,
void * const p2[6], const int p3[6],
const void * const p4[6], const int p5[6], int p6))
BEGIN_METHOD_RESOLVE()
RESOLVE_METHOD(avcodec_flush_buffers)
RESOLVE_METHOD_RENAME(avcodec_open2,avcodec_open2_dont_call)
Expand Down Expand Up @@ -288,9 +251,6 @@ class DllAvCodec : public DllDynamic, DllAvCodecInterface
RESOLVE_METHOD(avcodec_default_release_buffer)
RESOLVE_METHOD(avcodec_default_get_format)
RESOLVE_METHOD(av_codec_next)
RESOLVE_METHOD(av_audio_convert_alloc)
RESOLVE_METHOD(av_audio_convert_free)
RESOLVE_METHOD(av_audio_convert)
RESOLVE_METHOD(av_dup_packet)
RESOLVE_METHOD(av_init_packet)
END_METHOD_RESOLVE()
Expand Down
26 changes: 24 additions & 2 deletions lib/DllSwResample.h
Expand Up @@ -42,11 +42,20 @@ extern "C" {
#endif
}

class DllSwResampleInterface
{
public:
virtual ~DllSwResampleInterface() {}
virtual struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx)=0;
virtual int swr_init(struct SwrContext *s)=0;
virtual void swr_free(struct SwrContext **s)=0;
virtual int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in , int in_count)=0;
};

#if (defined USE_EXTERNAL_FFMPEG) || (defined TARGET_DARWIN)

// Use direct mapping
class DllSwResample : public DllDynamic
class DllSwResample : public DllDynamic, DllSwResampleInterface
{
public:
virtual ~DllSwResample() {}
Expand All @@ -58,17 +67,30 @@ class DllSwResample : public DllDynamic
return true;
}
virtual void Unload() {}
virtual struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx) { return ::swr_alloc_set_opts(s, out_ch_layout, out_sample_fmt, out_sample_rate, in_ch_layout, in_sample_fmt, in_sample_rate, log_offset, log_ctx); }
virtual int swr_init(struct SwrContext *s) { return ::swr_init(s); }
virtual void swr_free(struct SwrContext **s){ return ::swr_free(s); }
virtual int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in , int in_count){ return ::swr_convert(s, out, out_count, in, in_count); }
};

#else

class DllSwResample : public DllDynamic
class DllSwResample : public DllDynamic, DllSwResampleInterface
{
DECLARE_DLL_WRAPPER(DllSwResample, DLL_PATH_LIBSWRESAMPLE)

LOAD_SYMBOLS()

DEFINE_METHOD9(SwrContext*, swr_alloc_set_opts, (struct SwrContext *p1, int64_t p2, enum AVSampleFormat p3, int p4, int64_t p5, enum AVSampleFormat p6, int p7, int p8, void * p9));
DEFINE_METHOD1(int, swr_init, (struct SwrContext *p1))
DEFINE_METHOD1(void, swr_free, (struct SwrContext **p1))
DEFINE_METHOD5(int, swr_convert, (struct SwrContext *p1, uint8_t **p2, int p3, const uint8_t **p4, int p5))

BEGIN_METHOD_RESOLVE()
RESOLVE_METHOD(swr_alloc_set_opts)
RESOLVE_METHOD(swr_init)
RESOLVE_METHOD(swr_free)
RESOLVE_METHOD(swr_convert)
END_METHOD_RESOLVE()

/* dependencies of libavformat */
Expand Down
25 changes: 11 additions & 14 deletions xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp
Expand Up @@ -55,7 +55,7 @@ bool CDVDAudioCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
AVCodec* pCodec;
m_bOpenedCodec = false;

if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load())
if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllSwResample.Load())
return false;

m_dllAvCodec.avcodec_register_all();
Expand Down Expand Up @@ -112,8 +112,7 @@ void CDVDAudioCodecFFmpeg::Dispose()

if (m_pConvert)
{
m_dllAvCodec.av_audio_convert_free(m_pConvert);
m_pConvert = NULL;
m_dllSwResample.swr_free(&m_pConvert);
}

if (m_pCodecContext)
Expand Down Expand Up @@ -172,30 +171,28 @@ int CDVDAudioCodecFFmpeg::Decode(BYTE* pData, int iSize)
{
if(m_pConvert && m_pCodecContext->sample_fmt != m_iSampleFormat)
{
m_dllAvCodec.av_audio_convert_free(m_pConvert);
m_pConvert = NULL;
m_dllSwResample.swr_free(&m_pConvert);
}

if(!m_pConvert)
{
m_iSampleFormat = m_pCodecContext->sample_fmt;
m_pConvert = m_dllAvCodec.av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1, m_pCodecContext->sample_fmt, 1, NULL, 0);
m_pConvert = m_dllSwResample.swr_alloc_set_opts(NULL,
m_dllAvUtil.av_get_default_channel_layout(1), AV_SAMPLE_FMT_S16, m_pCodecContext->sample_rate,
m_dllAvUtil.av_get_default_channel_layout(1), m_pCodecContext->sample_fmt, m_pCodecContext->sample_rate,
0, NULL);
}

if(!m_pConvert)
if(!m_pConvert || m_dllSwResample.swr_init(m_pConvert))
{
CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Decode - Unable to convert %d to AV_SAMPLE_FMT_S16", m_pCodecContext->sample_fmt);
m_iBufferSize1 = 0;
m_iBufferSize2 = 0;
return iBytesUsed;
}

const void *ibuf[6] = { m_pFrame1->data[0] };
void *obuf[6] = { m_pBuffer2 };
int istr[6] = { m_dllAvUtil.av_get_bytes_per_sample(m_pCodecContext->sample_fmt) };
int ostr[6] = { 2 };
int len = m_iBufferSize1 / istr[0];
if(m_dllAvCodec.av_audio_convert(m_pConvert, obuf, ostr, ibuf, istr, len) < 0)
int len = m_iBufferSize1 / m_dllAvUtil.av_get_bytes_per_sample(m_pCodecContext->sample_fmt);
if(m_dllSwResample.swr_convert(m_pConvert, &m_pBuffer2, len, (const uint8_t**)m_pFrame1->data, m_pFrame1->nb_samples) < 0)
{
CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Decode - Unable to convert %d to AV_SAMPLE_FMT_S16", (int)m_pCodecContext->sample_fmt);
m_iBufferSize1 = 0;
Expand All @@ -204,7 +201,7 @@ int CDVDAudioCodecFFmpeg::Decode(BYTE* pData, int iSize)
}

m_iBufferSize1 = 0;
m_iBufferSize2 = len * ostr[0];
m_iBufferSize2 = len * 2;
}

return iBytesUsed;
Expand Down
4 changes: 3 additions & 1 deletion xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h
Expand Up @@ -25,6 +25,7 @@
#include "DllAvCodec.h"
#include "DllAvFormat.h"
#include "DllAvUtil.h"
#include "DllSwResample.h"

class CDVDAudioCodecFFmpeg : public CDVDAudioCodec
{
Expand All @@ -46,7 +47,7 @@ class CDVDAudioCodecFFmpeg : public CDVDAudioCodec

protected:
AVCodecContext* m_pCodecContext;
AVAudioConvert* m_pConvert;;
struct SwrContext* m_pConvert;;
enum AVSampleFormat m_iSampleFormat;
enum PCMChannels m_channelMap[PCM_MAX_CH + 1];

Expand All @@ -64,6 +65,7 @@ class CDVDAudioCodecFFmpeg : public CDVDAudioCodec

DllAvCodec m_dllAvCodec;
DllAvUtil m_dllAvUtil;
DllSwResample m_dllSwResample;

void BuildChannelMap();
};
Expand Down
Expand Up @@ -42,10 +42,10 @@ CDVDAudioEncoderFFmpeg::~CDVDAudioEncoderFFmpeg()
m_dllAvUtil.av_freep(&m_CodecCtx);
}

if(m_dllAvCodec.IsLoaded())
if(m_dllSwResample.IsLoaded())
{
if (m_AudioConvert)
m_dllAvCodec.av_audio_convert_free(m_AudioConvert);
m_dllSwResample.swr_free(&m_AudioConvert);
}
delete[] m_Buffer;
delete[] m_TmpBuffer;
Expand All @@ -55,7 +55,7 @@ CDVDAudioEncoderFFmpeg::~CDVDAudioEncoderFFmpeg()
bool CDVDAudioEncoderFFmpeg::Initialize(unsigned int channels, enum PCMChannels *channelMap, unsigned int bitsPerSample, unsigned int sampleRate)
{
Reset();
if (!channelMap || !m_dllAvUtil.Load() || !m_dllAvCodec.Load())
if (!channelMap || !m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllSwResample.Load())
return false;

m_dllAvCodec.avcodec_register_all();
Expand Down Expand Up @@ -93,9 +93,11 @@ bool CDVDAudioEncoderFFmpeg::Initialize(unsigned int channels, enum PCMChannels
/* the input format was not supported, initiate conversion to the first
* supported format */
CLog::Log(LOGDEBUG, "CDVDAudioEncoderFFmpeg: Initializing audio conversion for encoding");
m_AudioConvert = m_dllAvCodec.av_audio_convert_alloc(codec->sample_fmts[0], 1,
m_CodecCtx->sample_fmt, 1, NULL, 0);
if (!m_AudioConvert)
m_AudioConvert = m_dllSwResample.swr_alloc_set_opts(NULL,
m_dllAvUtil.av_get_default_channel_layout(1), codec->sample_fmts[0], codec->supported_samplerates ? codec->supported_samplerates[0] : m_CodecCtx->sample_rate,
m_dllAvUtil.av_get_default_channel_layout(1), m_CodecCtx->sample_fmt, m_CodecCtx->sample_rate,
0, NULL);
if (!m_AudioConvert || m_dllSwResample.swr_init(m_AudioConvert))
{
m_dllAvUtil.av_freep(&m_CodecCtx);
return false;
Expand Down Expand Up @@ -183,12 +185,9 @@ int CDVDAudioEncoderFFmpeg::Encode(uint8_t *data, int size)
m_Remap.Remap(data, m_TmpBuffer, m_NeededFrames);

if (m_AudioConvert) {
void *convInBuf[] = { m_TmpBuffer };
int convInStr[] = { m_BitsPerSample / 8 };
void *convOutBuf[] = { m_TmpBuffer2 };
int convOutStr[] = { m_dllAvUtil.av_get_bytes_per_sample(m_CodecCtx->sample_fmt) };
if (m_dllAvCodec.av_audio_convert(m_AudioConvert, convOutBuf, convOutStr,
convInBuf, convInStr, m_NeededFrames * m_CodecCtx->channels) < 0) {
if (m_dllSwResample.swr_convert(m_AudioConvert,
&m_TmpBuffer2, m_NeededFrames * m_CodecCtx->channels,
(const uint8_t**)&m_TmpBuffer, m_NeededFrames * m_CodecCtx->channels) < 0) {
CLog::Log(LOGERROR, "CDVDAudioEncoderFFmpeg: Audio conversion failed");
m_BufferSize = 0;
return m_NeededBytes;
Expand Down
Expand Up @@ -24,6 +24,7 @@
#include "DllAvCodec.h"
#include "DllAvFormat.h"
#include "DllAvUtil.h"
#include "DllSwResample.h"

class CDVDAudioEncoderFFmpeg: public IDVDAudioEncoder
{
Expand All @@ -44,9 +45,10 @@ class CDVDAudioEncoderFFmpeg: public IDVDAudioEncoder
private:
DllAvCodec m_dllAvCodec;
DllAvUtil m_dllAvUtil;
DllSwResample m_dllSwResample;

AVCodecContext *m_CodecCtx;
AVAudioConvert *m_AudioConvert;
SwrContext *m_AudioConvert;
enum PCMChannels m_ChannelMap[PCM_MAX_CH];
CPCMRemap m_Remap;
uint8_t *m_Buffer;
Expand Down