Skip to content

Commit

Permalink
Fix sound with recent FFmpeg by converting from av_audio_convert API …
Browse files Browse the repository at this point in the history
…to the swresample one
  • Loading branch information
Sébastien NOEL committed Jan 23, 2013
1 parent 87cbcde commit 462a01b
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 64 deletions.
40 changes: 0 additions & 40 deletions DllAvCodec.h
Original file line number Diff line number Diff line change
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 @@ -184,17 +165,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 @@ -246,13 +216,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 @@ -283,9 +246,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
68 changes: 65 additions & 3 deletions DllSwResample.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "config.h"
#endif
#include "DynamicDll.h"
#include "utils/log.h"

extern "C" {
#ifndef HAVE_MMX
Expand All @@ -36,17 +37,36 @@ extern "C" {
#pragma warning(disable:4244)
#endif
#if (defined USE_EXTERNAL_FFMPEG)
#include <libswresample/swresample.h>
#if HAVE_LIBSWRESAMPLE_SWRESAMPLE_H
#include <libswresample/swresample.h>
#elif HAVE_LIBAVRESAMPLE_AVRESAMPLE_H
#include <libavresample/avresample.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#define SwrContext AVAudioResampleContext
#else
#error "Either libswresample or libavresample is needed!"
#endif
#else
#include "libswresample/swresample.h"
#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)

#if HAVE_LIBSWRESAMPLE_SWRESAMPLE_H || (defined TARGET_DARWIN)
// Use direct mapping
class DllSwResample : public DllDynamic
class DllSwResample : public DllDynamic, DllSwResampleInterface
{
public:
virtual ~DllSwResample() {}
Expand All @@ -58,17 +78,59 @@ 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
// Wrap the same API through libavresample.
class DllSwResample : public DllDynamic, DllSwResampleInterface
{
public:
virtual ~DllSwResample() {}

// DLL faking.
virtual bool ResolveExports() { return true; }
virtual bool Load() {
CLog::Log(LOGDEBUG, "DllAvFormat: Using libavresample system library");
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) {
AVAudioResampleContext *ret = ::avresample_alloc_context();
av_opt_set_int(ret, "out_channel_layout", out_ch_layout , 0);
av_opt_set_int(ret, "out_sample_fmt" , out_sample_fmt , 0);
av_opt_set_int(ret, "out_sample_rate" , out_sample_rate, 0);
av_opt_set_int(ret, "in_channel_layout" , in_ch_layout , 0);
av_opt_set_int(ret, "in_sample_fmt" , in_sample_fmt , 0);
av_opt_set_int(ret, "in_sample_rate" , in_sample_rate , 0);
return ret;
}
virtual int swr_init(struct SwrContext *s) { return ::avresample_open(s); }
virtual void swr_free(struct SwrContext **s){ ::avresample_close(*s); *s = NULL; }
virtual int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in , int in_count){ return ::avresample_convert(s, (void**)out, 0, out_count, (void**)in, 0,in_count); }
};
#endif

#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
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include Makefile.include

CFLAGS+=-std=c++0x -DSTANDALONE -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS -DTARGET_POSIX -D_LINUX -fPIC -DPIC -D_REENTRANT -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CMAKE_CONFIG -D__VIDEOCORE4__ -U_FORTIFY_SOURCE -Wall -DHAVE_OMXLIB -DUSE_EXTERNAL_FFMPEG -DHAVE_LIBAVCODEC_AVCODEC_H -DHAVE_LIBAVUTIL_OPT_H -DHAVE_LIBAVUTIL_MEM_H -DHAVE_LIBAVUTIL_AVUTIL_H -DHAVE_LIBAVFORMAT_AVFORMAT_H -DHAVE_LIBAVFILTER_AVFILTER_H -DOMX -DOMX_SKIP64BIT -ftree-vectorize -DUSE_EXTERNAL_OMX -DTARGET_RASPBERRY_PI -DUSE_EXTERNAL_LIBBCM_HOST
CFLAGS+=-std=c++0x -DSTANDALONE -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS -DTARGET_POSIX -D_LINUX -fPIC -DPIC -D_REENTRANT -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CMAKE_CONFIG -D__VIDEOCORE4__ -U_FORTIFY_SOURCE -Wall -DHAVE_OMXLIB -DUSE_EXTERNAL_FFMPEG -DHAVE_LIBAVCODEC_AVCODEC_H -DHAVE_LIBAVUTIL_OPT_H -DHAVE_LIBAVUTIL_MEM_H -DHAVE_LIBAVUTIL_AVUTIL_H -DHAVE_LIBAVFORMAT_AVFORMAT_H -DHAVE_LIBAVFILTER_AVFILTER_H -DHAVE_LIBSWRESAMPLE_SWRESAMPLE_H -DOMX -DOMX_SKIP64BIT -ftree-vectorize -DUSE_EXTERNAL_OMX -DTARGET_RASPBERRY_PI -DUSE_EXTERNAL_LIBBCM_HOST

LDFLAGS+=-L./ -lc -lWFC -lGLESv2 -lEGL -lbcm_host -lopenmaxil -lfreetype -lz -Lffmpeg_compiled/usr/local/lib/
INCLUDES+=-I./ -Ilinux -Iffmpeg_compiled/usr/local/include/
Expand Down Expand Up @@ -44,7 +44,7 @@ list_test:
$(CXX) -O3 -o list_test list_test.cpp

omxplayer.bin: $(OBJS)
$(CXX) $(LDFLAGS) -o omxplayer.bin $(OBJS) -lvchiq_arm -lvcos -lrt -lpthread -lavutil -lavcodec -lavformat -lswscale -lpcre
$(CXX) $(LDFLAGS) -o omxplayer.bin $(OBJS) -lvchiq_arm -lvcos -lrt -lpthread -lavutil -lavcodec -lavformat -lswscale -lswresample -lpcre
#arm-unknown-linux-gnueabi-strip omxplayer.bin

clean:
Expand Down
32 changes: 14 additions & 18 deletions OMXAudioCodecOMX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ bool COMXAudioCodecOMX::Open(COMXStreamInfo &hints)
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 @@ -114,10 +114,7 @@ void COMXAudioCodecOMX::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 All @@ -129,6 +126,7 @@ void COMXAudioCodecOMX::Dispose()

m_dllAvCodec.Unload();
m_dllAvUtil.Unload();
m_dllSwResample.Unload();

m_iBufferSize1 = 0;
m_iBufferSize2 = 0;
Expand Down Expand Up @@ -174,31 +172,29 @@ int COMXAudioCodecOMX::Decode(BYTE* pData, int iSize)
if(m_pCodecContext->sample_fmt != AV_SAMPLE_FMT_S16 && m_iBufferSize1 > 0)
{
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(m_pCodecContext->channels),
AV_SAMPLE_FMT_S16, m_pCodecContext->sample_rate,
m_dllAvUtil.av_get_default_channel_layout(m_pCodecContext->channels),
m_pCodecContext->sample_fmt, m_pCodecContext->sample_rate,
0, NULL);
}

if(!m_pConvert)
if(!m_pConvert || m_dllSwResample.swr_init(m_pConvert) < 0)
{
CLog::Log(LOGERROR, "COMXAudioCodecOMX::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, "COMXAudioCodecOMX::Decode - Unable to convert %d to AV_SAMPLE_FMT_S16", (int)m_pCodecContext->sample_fmt);
m_iBufferSize1 = 0;
Expand All @@ -207,7 +203,7 @@ int COMXAudioCodecOMX::Decode(BYTE* pData, int iSize)
}

m_iBufferSize1 = 0;
m_iBufferSize2 = len * ostr[0];
m_iBufferSize2 = len * m_dllAvUtil.av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
}

return iBytesUsed;
Expand Down
4 changes: 3 additions & 1 deletion OMXAudioCodecOMX.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "DllAvCodec.h"
#include "DllAvFormat.h"
#include "DllAvUtil.h"
#include "DllSwResample.h"

#include "OMXStreamInfo.h"
#include "utils/PCMRemap.h"
Expand All @@ -49,7 +50,7 @@ class COMXAudioCodecOMX

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

Expand All @@ -67,6 +68,7 @@ class COMXAudioCodecOMX

DllAvCodec m_dllAvCodec;
DllAvUtil m_dllAvUtil;
DllSwResample m_dllSwResample;

void BuildChannelMap();
};

0 comments on commit 462a01b

Please sign in to comment.