History

Merge remote-tracking branch 'qatar/master'

* qatar/master: FATE: use updated reference for aac-latm_stereo_to_51 avconv: use libavresample Add libavresample FATE: avoid channel mixing in lavf-dv_fmt Conflicts: Changelog Makefile cmdutils.c configure doc/APIchanges ffmpeg.c tests/lavf-regression.sh tests/ref/lavf/dv_fmt tests/ref/seek/lavf_dv

Michael Niedermayer committed 14 years ago

Commit 3ead79e2 parents cab15f9 394dbde33 files · +3875 −27Browse files

Unified · Split

33 files
  1. Changelog +1 −0
  2. Makefile +1 −0
  3. cmdutils.c +4 −1
  4. common.mak +1 −1
  5. configure +5 −0
  6. doc/APIchanges +4 −0
  7. ffmpeg.c +35 −20
  8. libavresample/Makefile +15 −0
  9. libavresample/audio_convert.c +334 −0
  10. libavresample/audio_convert.h +87 −0
  11. libavresample/audio_data.c +345 −0
  12. libavresample/audio_data.h +173 −0
  13. libavresample/audio_mix.c +356 −0
  14. libavresample/audio_mix.h +108 −0
  15. libavresample/audio_mix_matrix.c +346 −0
  16. libavresample/avresample-test.c +340 −0
  17. libavresample/avresample.h +283 −0
  18. libavresample/internal.h +75 −0
  19. libavresample/libavresample.v +4 −0
  20. libavresample/options.c +89 −0
  21. libavresample/resample.c +480 −0
  22. libavresample/resample.h +70 −0
  23. libavresample/utils.c +405 −0
  24. libavresample/version.h +41 −0
  25. libavresample/x86/Makefile +5 −0
  26. libavresample/x86/audio_convert.asm +104 −0
  27. libavresample/x86/audio_convert_init.c +42 −0
  28. libavresample/x86/audio_mix.asm +64 −0
  29. libavresample/x86/audio_mix_init.c +44 −0
  30. libavutil/x86/x86util.asm +9 −0
  31. tests/fate/aac.mak +2 −2
  32. tests/lavf-regression.sh +1 −1
  33. tests/ref/lavf/dv_fmt +2 −2
Changelog+1−0
@@ -26,6 +26,7 @@ version next: · 25 unmodified lines
26- drawtext video filter: fontconfig support26- drawtext video filter: fontconfig support
27- ffmpeg -benchmark_all option27- ffmpeg -benchmark_all option
28- super2xsai filter ported from libmpcodecs28- super2xsai filter ported from libmpcodecs
29- add libavresample audio conversion library for compatibility
29 30
30 31
31version 0.10:32version 0.10:
Makefile+1−0
@@ -31,6 +31,7 @@ ALLMANPAGES = $(BASENAMES:%=%.1) · 30 unmodified lines
31FFLIBS-$(CONFIG_AVDEVICE) += avdevice31FFLIBS-$(CONFIG_AVDEVICE) += avdevice
32FFLIBS-$(CONFIG_AVFILTER) += avfilter32FFLIBS-$(CONFIG_AVFILTER) += avfilter
33FFLIBS-$(CONFIG_AVFORMAT) += avformat33FFLIBS-$(CONFIG_AVFORMAT) += avformat
34FFLIBS-$(CONFIG_AVRESAMPLE) += avresample
34FFLIBS-$(CONFIG_AVCODEC) += avcodec35FFLIBS-$(CONFIG_AVCODEC) += avcodec
35FFLIBS-$(CONFIG_POSTPROC) += postproc36FFLIBS-$(CONFIG_POSTPROC) += postproc
36FFLIBS-$(CONFIG_SWRESAMPLE)+= swresample37FFLIBS-$(CONFIG_SWRESAMPLE)+= swresample
cmdutils.c+4−1
@@ -32,6 +32,7 @@ · 31 unmodified lines
32#include "libavformat/avformat.h"32#include "libavformat/avformat.h"
33#include "libavfilter/avfilter.h"33#include "libavfilter/avfilter.h"
34#include "libavdevice/avdevice.h"34#include "libavdevice/avdevice.h"
35#include "libavresample/avresample.h"
35#include "libswscale/swscale.h"36#include "libswscale/swscale.h"
36#include "libswresample/swresample.h"37#include "libswresample/swresample.h"
37#if CONFIG_POSTPROC38#if CONFIG_POSTPROC
@@ -633,7 +634,8 @@ static int warned_cfg = 0; · 595 unmodified lines
633 const char *indent = flags & INDENT? " " : ""; \634 const char *indent = flags & INDENT? " " : ""; \
634 if (flags & SHOW_VERSION) { \635 if (flags & SHOW_VERSION) { \
635 unsigned int version = libname##_version(); \636 unsigned int version = libname##_version(); \
636 av_log(NULL, level, "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n",\637 av_log(NULL, level, \
638 "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n", \
637 indent, #libname, \639 indent, #libname, \
638 LIB##LIBNAME##_VERSION_MAJOR, \640 LIB##LIBNAME##_VERSION_MAJOR, \
639 LIB##LIBNAME##_VERSION_MINOR, \641 LIB##LIBNAME##_VERSION_MINOR, \
@@ -662,6 +664,7 @@ static void print_all_libs_info(int flags, int level) · 22 unmodified lines
662 PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);664 PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);
663 PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);665 PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);
664 PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);666 PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);
667// PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
665 PRINT_LIB_INFO(swscale, SWSCALE, flags, level);668 PRINT_LIB_INFO(swscale, SWSCALE, flags, level);
666 PRINT_LIB_INFO(swresample,SWRESAMPLE, flags, level);669 PRINT_LIB_INFO(swresample,SWRESAMPLE, flags, level);
667#if CONFIG_POSTPROC670#if CONFIG_POSTPROC
common.mak+1−1
@@ -20,7 +20,7 @@ $(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR)))) · 19 unmodified lines
20$(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL))20$(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL))
21endif21endif
22 22
23ALLFFLIBS = avcodec avdevice avfilter avformat avutil postproc swscale swresample23ALLFFLIBS = avcodec avdevice avfilter avformat avresample avutil postproc swscale swresample
24 24
25# NASM requires -I path terminated with /25# NASM requires -I path terminated with /
26IFLAGS := -I. -I$(SRC_PATH)/26IFLAGS := -I. -I$(SRC_PATH)/
configure+5−0
@@ -112,6 +112,7 @@ Component options: · 111 unmodified lines
112 --disable-swscale disable libswscale build112 --disable-swscale disable libswscale build
113 --disable-postproc disable libpostproc build113 --disable-postproc disable libpostproc build
114 --disable-avfilter disable video filter support [no]114 --disable-avfilter disable video filter support [no]
115 --disable-avresample disable libavresample build [no]
115 --disable-pthreads disable pthreads [auto]116 --disable-pthreads disable pthreads [auto]
116 --disable-w32threads disable Win32 threads [auto]117 --disable-w32threads disable Win32 threads [auto]
117 --disable-os2threads disable OS/2 threads [auto]118 --disable-os2threads disable OS/2 threads [auto]
@@ -1013,6 +1014,7 @@ CONFIG_LIST=" · 895 unmodified lines
1013 avdevice1014 avdevice
1014 avfilter1015 avfilter
1015 avformat1016 avformat
1017 avresample
1016 avisynth1018 avisynth
1017 bzlib1019 bzlib
1018 crystalhd1020 crystalhd
@@ -1870,6 +1872,7 @@ enable avcodec · 851 unmodified lines
1870enable avdevice1872enable avdevice
1871enable avfilter1873enable avfilter
1872enable avformat1874enable avformat
1875enable avresample
1873enable avutil1876enable avutil
1874enable postproc1877enable postproc
1875enable stripping1878enable stripping
@@ -3724,6 +3727,7 @@ get_version LIBAVCODEC libavcodec/version.h · 1848 unmodified lines
3724get_version LIBAVDEVICE libavdevice/avdevice.h3727get_version LIBAVDEVICE libavdevice/avdevice.h
3725get_version LIBAVFILTER libavfilter/version.h3728get_version LIBAVFILTER libavfilter/version.h
3726get_version LIBAVFORMAT libavformat/version.h3729get_version LIBAVFORMAT libavformat/version.h
3730get_version LIBAVRESAMPLE libavresample/version.h
3727get_version LIBAVUTIL libavutil/avutil.h3731get_version LIBAVUTIL libavutil/avutil.h
3728get_version LIBPOSTPROC libpostproc/postprocess.h3732get_version LIBPOSTPROC libpostproc/postprocess.h
3729get_version LIBSWRESAMPLE libswresample/swresample.h3733get_version LIBSWRESAMPLE libswresample/swresample.h
@@ -3869,5 +3873,6 @@ pkgconfig_generate libavformat "FFmpeg container format library" "$LIBAVFORMAT_V · 139 unmodified lines
3869pkgconfig_generate libavdevice "FFmpeg device handling library" "$LIBAVDEVICE_VERSION" "$extralibs" "$libavdevice_pc_deps"3873pkgconfig_generate libavdevice "FFmpeg device handling library" "$LIBAVDEVICE_VERSION" "$extralibs" "$libavdevice_pc_deps"
3870pkgconfig_generate libavfilter "FFmpeg video filtering library" "$LIBAVFILTER_VERSION" "$extralibs" "$libavfilter_pc_deps"3874pkgconfig_generate libavfilter "FFmpeg video filtering library" "$LIBAVFILTER_VERSION" "$extralibs" "$libavfilter_pc_deps"
3871pkgconfig_generate libpostproc "FFmpeg postprocessing library" "$LIBPOSTPROC_VERSION" "" "libavutil = $LIBAVUTIL_VERSION"3875pkgconfig_generate libpostproc "FFmpeg postprocessing library" "$LIBPOSTPROC_VERSION" "" "libavutil = $LIBAVUTIL_VERSION"
3876pkgconfig_generate libavresample "Libav audio resampling library" "$LIBAVRESAMPLE_VERSION" "$extralibs"
3872pkgconfig_generate libswscale "FFmpeg image rescaling library" "$LIBSWSCALE_VERSION" "$LIBM" "libavutil = $LIBAVUTIL_VERSION"3877pkgconfig_generate libswscale "FFmpeg image rescaling library" "$LIBSWSCALE_VERSION" "$LIBM" "libavutil = $LIBAVUTIL_VERSION"
3873pkgconfig_generate libswresample "FFmpeg audio rescaling library" "$LIBSWRESAMPLE_VERSION" "$LIBM" "libavutil = $LIBAVUTIL_VERSION"3878pkgconfig_generate libswresample "FFmpeg audio rescaling library" "$LIBSWRESAMPLE_VERSION" "$LIBM" "libavutil = $LIBAVUTIL_VERSION"
doc/APIchanges+4−0
@@ -6,6 +6,7 @@ libavcodec: 2012-01-27 · 5 unmodified lines
6libavdevice: 2011-04-186libavdevice: 2011-04-18
7libavfilter: 2011-04-187libavfilter: 2011-04-18
8libavformat: 2012-01-278libavformat: 2012-01-27
9libavresample: 2012-xx-xx
9libpostproc: 2011-04-1810libpostproc: 2011-04-18
10libswscale: 2011-06-2011libswscale: 2011-06-20
11libavutil: 2011-04-1812libavutil: 2011-04-18
@@ -22,6 +23,9 @@ API changes, most recent first: · 10 unmodified lines
222012-03-26 - a67d9cf - lavfi 2.66.100232012-03-26 - a67d9cf - lavfi 2.66.100
23 Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions.24 Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions.
24 25
262012-xx-xx - xxxxxxx - lavr 0.0.0
27 Add libavresample audio conversion library
28
252012-xx-xx - xxxxxxx - lavu 51.28.0 - audio_fifo.h292012-xx-xx - xxxxxxx - lavu 51.28.0 - audio_fifo.h
26 Add audio FIFO functions:30 Add audio FIFO functions:
27 av_audio_fifo_free()31 av_audio_fifo_free()
ffmpeg.c+35−20
@@ -36,7 +36,6 @@ · 35 unmodified lines
36#include "libavdevice/avdevice.h"36#include "libavdevice/avdevice.h"
37#include "libswscale/swscale.h"37#include "libswscale/swscale.h"
38#include "libavutil/opt.h"38#include "libavutil/opt.h"
39#include "libavcodec/audioconvert.h"
40#include "libavutil/audioconvert.h"39#include "libavutil/audioconvert.h"
41#include "libavutil/parseutils.h"40#include "libavutil/parseutils.h"
42#include "libavutil/samplefmt.h"41#include "libavutil/samplefmt.h"
@@ -300,6 +299,7 @@ typedef struct OutputStream { · 257 unmodified lines
300 int audio_channels_mapped; ///< number of channels in audio_channels_map299 int audio_channels_mapped; ///< number of channels in audio_channels_map
301 int resample_sample_fmt;300 int resample_sample_fmt;
302 int resample_channels;301 int resample_channels;
302 uint64_t resample_channel_layout;
303 int resample_sample_rate;303 int resample_sample_rate;
304 float rematrix_volume;304 float rematrix_volume;
305 AVFifoBuffer *fifo; /* for compression: one audio fifo per codec */305 AVFifoBuffer *fifo; /* for compression: one audio fifo per codec */
@@ -1525,7 +1525,7 @@ static int encode_audio_frame(AVFormatContext *s, OutputStream *ost, · 1219 unmodified lines
1525}1525}
1526 1526
1527static int alloc_audio_output_buf(AVCodecContext *dec, AVCodecContext *enc,1527static int alloc_audio_output_buf(AVCodecContext *dec, AVCodecContext *enc,
1528 int nb_samples)1528 int nb_samples, int *buf_linesize)
1529{1529{
1530 int64_t audio_buf_samples;1530 int64_t audio_buf_samples;
1531 int audio_buf_size;1531 int audio_buf_size;
@@ -1538,7 +1538,7 @@ static int alloc_audio_output_buf(AVCodecContext *dec, AVCodecContext *enc, · 6 unmodified lines
1538 if (audio_buf_samples > INT_MAX)1538 if (audio_buf_samples > INT_MAX)
1539 return AVERROR(EINVAL);1539 return AVERROR(EINVAL);
1540 1540
1541 audio_buf_size = av_samples_get_buffer_size(NULL, enc->channels,1541 audio_buf_size = av_samples_get_buffer_size(buf_linesize, enc->channels,
1542 audio_buf_samples,1542 audio_buf_samples,
1543 enc->sample_fmt, 0);1543 enc->sample_fmt, 0);
1544 if (audio_buf_size < 0)1544 if (audio_buf_size < 0)
@@ -1557,7 +1557,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 12 unmodified lines
1557 uint8_t *buftmp;1557 uint8_t *buftmp;
1558 int64_t size_out;1558 int64_t size_out;
1559 1559
1560 int frame_bytes, resample_changed;1560 int frame_bytes, resample_changed, ret;
1561 AVCodecContext *enc = ost->st->codec;1561 AVCodecContext *enc = ost->st->codec;
1562 AVCodecContext *dec = ist->st->codec;1562 AVCodecContext *dec = ist->st->codec;
1563 int osize = av_get_bytes_per_sample(enc->sample_fmt);1563 int osize = av_get_bytes_per_sample(enc->sample_fmt);
@@ -1566,37 +1566,46 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 2 unmodified lines
1566 int size = decoded_frame->nb_samples * dec->channels * isize;1566 int size = decoded_frame->nb_samples * dec->channels * isize;
1567 int planes = av_sample_fmt_is_planar(dec->sample_fmt) ? dec->channels : 1;1567 int planes = av_sample_fmt_is_planar(dec->sample_fmt) ? dec->channels : 1;
1568 int i;1568 int i;
1569 int out_linesize = 0;
1570 int buf_linesize = decoded_frame->linesize[0];
1569 1571
1570 av_assert0(planes <= AV_NUM_DATA_POINTERS);1572 av_assert0(planes <= AV_NUM_DATA_POINTERS);
1571 1573
1572 for(i=0; i<planes; i++)1574 for(i=0; i<planes; i++)
1573 buf[i]= decoded_frame->data[i];1575 buf[i]= decoded_frame->data[i];
1574 1576
1577
1575 get_default_channel_layouts(ost, ist);1578 get_default_channel_layouts(ost, ist);
1576 1579
1577 if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples) < 0) {1580 if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples, &out_linesize) < 0) {
1578 av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");1581 av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");
1579 exit_program(1);1582 exit_program(1);
1580 }1583 }
1581 1584
1582 if (enc->channels != dec->channels1585 if (audio_sync_method > 1 ||
1583 || enc->sample_fmt != dec->sample_fmt1586 enc->channels != dec->channels ||
1584 || enc->sample_rate!= dec->sample_rate1587 enc->channel_layout != dec->channel_layout ||
1585 )1588 enc->sample_rate != dec->sample_rate ||
1589 dec->sample_fmt != enc->sample_fmt)
1586 ost->audio_resample = 1;1590 ost->audio_resample = 1;
1587 1591
1588 resample_changed = ost->resample_sample_fmt != dec->sample_fmt ||1592 resample_changed = ost->resample_sample_fmt != dec->sample_fmt ||
1589 ost->resample_channels != dec->channels ||1593 ost->resample_channels != dec->channels ||
1594 ost->resample_channel_layout != dec->channel_layout ||
1590 ost->resample_sample_rate != dec->sample_rate;1595 ost->resample_sample_rate != dec->sample_rate;
1591 1596
1592 if ((ost->audio_resample && !ost->swr) || resample_changed || ost->audio_channels_mapped) {1597 if ((ost->audio_resample && !ost->swr) || resample_changed || ost->audio_channels_mapped) {
1598
1593 if (resample_changed) {1599 if (resample_changed) {
1594 av_log(NULL, AV_LOG_INFO, "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d to rate:%d fmt:%s ch:%d\n",1600 av_log(NULL, AV_LOG_INFO, "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d chl:0x%"PRIx64" to rate:%d fmt:%s ch:%d chl:0x%"PRIx64"\n",
1595 ist->file_index, ist->st->index,1601 ist->file_index, ist->st->index,
1596 ost->resample_sample_rate, av_get_sample_fmt_name(ost->resample_sample_fmt), ost->resample_channels,1602 ost->resample_sample_rate, av_get_sample_fmt_name(ost->resample_sample_fmt),
1597 dec->sample_rate, av_get_sample_fmt_name(dec->sample_fmt), dec->channels);1603 ost->resample_channels, ost->resample_channel_layout,
1604 dec->sample_rate, av_get_sample_fmt_name(dec->sample_fmt),
1605 dec->channels, dec->channel_layout);
1598 ost->resample_sample_fmt = dec->sample_fmt;1606 ost->resample_sample_fmt = dec->sample_fmt;
1599 ost->resample_channels = dec->channels;1607 ost->resample_channels = dec->channels;
1608 ost->resample_channel_layout = dec->channel_layout;
1600 ost->resample_sample_rate = dec->sample_rate;1609 ost->resample_sample_rate = dec->sample_rate;
1601 swr_free(&ost->swr);1610 swr_free(&ost->swr);
1602 }1611 }
@@ -1604,6 +1613,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 1 unmodified line
1604 if (audio_sync_method <= 1 && !ost->audio_channels_mapped &&1613 if (audio_sync_method <= 1 && !ost->audio_channels_mapped &&
1605 ost->resample_sample_fmt == enc->sample_fmt &&1614 ost->resample_sample_fmt == enc->sample_fmt &&
1606 ost->resample_channels == enc->channels &&1615 ost->resample_channels == enc->channels &&
1616 ost->resample_channel_layout == enc->channel_layout &&
1607 ost->resample_sample_rate == enc->sample_rate) {1617 ost->resample_sample_rate == enc->sample_rate) {
1608 //ost->swr = NULL;1618 //ost->swr = NULL;
1609 ost->audio_resample = 0;1619 ost->audio_resample = 0;
@@ -1673,7 +1683,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 63 unmodified lines
1673 exit_program(1);1683 exit_program(1);
1674 }1684 }
1675 1685
1676 if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples + idelta) < 0) {1686 if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples + idelta, &out_linesize) < 0) {
1677 av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");1687 av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");
1678 exit_program(1);1688 exit_program(1);
1679 }1689 }
@@ -1686,11 +1696,11 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 6 unmodified lines
1686 buf[i] = t;1696 buf[i] = t;
1687 }1697 }
1688 size += byte_delta;1698 size += byte_delta;
1699 buf_linesize = allocated_async_buf_size;
1689 av_log(NULL, AV_LOG_VERBOSE, "adding %d audio samples of silence\n", idelta);1700 av_log(NULL, AV_LOG_VERBOSE, "adding %d audio samples of silence\n", idelta);
1690 }1701 }
1691 } else if (audio_sync_method > 1) {1702 } else if (audio_sync_method > 1) {
1692 int comp = av_clip(delta, -audio_sync_method, audio_sync_method);1703 int comp = av_clip(delta, -audio_sync_method, audio_sync_method);
1693 av_assert0(ost->audio_resample);
1694 av_log(NULL, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n",1704 av_log(NULL, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n",
1695 delta, comp, enc->sample_rate);1705 delta, comp, enc->sample_rate);
1696// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2));1706// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2));
@@ -1703,8 +1713,10 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, · 6 unmodified lines
1703 1713
1704 if (ost->audio_resample || ost->audio_channels_mapped) {1714 if (ost->audio_resample || ost->audio_channels_mapped) {
1705 buftmp = audio_buf;1715 buftmp = audio_buf;
1706 size_out = swr_convert(ost->swr, ( uint8_t*[]){buftmp}, allocated_audio_buf_size / (enc->channels * osize),1716 size_out = swr_convert(ost->swr, ( uint8_t*[]){buftmp},
1707 buf, size / (dec->channels * isize));1717 allocated_audio_buf_size / (enc->channels * osize),
1718 buf,
1719 size / (dec->channels * isize));
1708 if (size_out < 0) {1720 if (size_out < 0) {
1709 av_log(NULL, AV_LOG_FATAL, "swr_convert failed\n");1721 av_log(NULL, AV_LOG_FATAL, "swr_convert failed\n");
1710 exit_program(1);1722 exit_program(1);
@@ -3078,6 +3090,7 @@ static int transcode_init(void) · 1367 unmodified lines
3078 if (!ost->fifo) {3090 if (!ost->fifo) {
3079 return AVERROR(ENOMEM);3091 return AVERROR(ENOMEM);
3080 }3092 }
3093
3081 if (!codec->sample_rate)3094 if (!codec->sample_rate)
3082 codec->sample_rate = icodec->sample_rate;3095 codec->sample_rate = icodec->sample_rate;
3083 choose_sample_rate(ost->st, ost->enc);3096 choose_sample_rate(ost->st, ost->enc);
@@ -3110,13 +3123,15 @@ static int transcode_init(void) · 26 unmodified lines
3110 if (av_get_channel_layout_nb_channels(codec->channel_layout) != codec->channels)3123 if (av_get_channel_layout_nb_channels(codec->channel_layout) != codec->channels)
3111 codec->channel_layout = 0;3124 codec->channel_layout = 0;
3112 3125
3113 ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;3126
3114 ost->audio_resample |= codec->sample_fmt != icodec->sample_fmt3127// ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;
3115 || codec->channel_layout != icodec->channel_layout;3128// ost->audio_resample |= codec->sample_fmt != icodec->sample_fmt
3116 icodec->request_channels = codec->channels;3129// || codec->channel_layout != icodec->channel_layout;
3130 icodec->request_channels = codec-> channels;
3117 ost->resample_sample_fmt = icodec->sample_fmt;3131 ost->resample_sample_fmt = icodec->sample_fmt;
3118 ost->resample_sample_rate = icodec->sample_rate;3132 ost->resample_sample_rate = icodec->sample_rate;
3119 ost->resample_channels = icodec->channels;3133 ost->resample_channels = icodec->channels;
3134 ost->resample_channel_layout = icodec->channel_layout;
3120 break;3135 break;
3121 case AVMEDIA_TYPE_VIDEO:3136 case AVMEDIA_TYPE_VIDEO:
3122 if (!ost->filter) {3137 if (!ost->filter) {
libavresample/Makefile+15−0
@@ -0,0 +1,15 @@
1NAME = avresample
2FFLIBS = avutil
3
4HEADERS = avresample.h \
5 version.h
6
7OBJS = audio_convert.o \
8 audio_data.o \
9 audio_mix.o \
10 audio_mix_matrix.o \
11 options.o \
12 resample.o \
13 utils.o
14
15TESTPROGS = avresample
libavresample/audio_convert.c+334−0
@@ -0,0 +1,334 @@
1/*
2 * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 *
5 * This file is part of Libav.
6 *
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdint.h>
23
24#include "config.h"
25#include "libavutil/libm.h"
26#include "libavutil/log.h"
27#include "libavutil/mem.h"
28#include "libavutil/samplefmt.h"
29#include "audio_convert.h"
30#include "audio_data.h"
31
32enum ConvFuncType {
33 CONV_FUNC_TYPE_FLAT,
34 CONV_FUNC_TYPE_INTERLEAVE,
35 CONV_FUNC_TYPE_DEINTERLEAVE,
36};
37
38typedef void (conv_func_flat)(uint8_t *out, const uint8_t *in, int len);
39
40typedef void (conv_func_interleave)(uint8_t *out, uint8_t *const *in,
41 int len, int channels);
42
43typedef void (conv_func_deinterleave)(uint8_t **out, const uint8_t *in, int len,
44 int channels);
45
46struct AudioConvert {
47 AVAudioResampleContext *avr;
48 enum AVSampleFormat in_fmt;
49 enum AVSampleFormat out_fmt;
50 int channels;
51 int planes;
52 int ptr_align;
53 int samples_align;
54 int has_optimized_func;
55 const char *func_descr;
56 const char *func_descr_generic;
57 enum ConvFuncType func_type;
58 conv_func_flat *conv_flat;
59 conv_func_flat *conv_flat_generic;
60 conv_func_interleave *conv_interleave;
61 conv_func_interleave *conv_interleave_generic;
62 conv_func_deinterleave *conv_deinterleave;
63 conv_func_deinterleave *conv_deinterleave_generic;
64};
65
66void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt,
67 enum AVSampleFormat in_fmt, int channels,
68 int ptr_align, int samples_align,
69 const char *descr, void *conv)
70{
71 int found = 0;
72
73 switch (ac->func_type) {
74 case CONV_FUNC_TYPE_FLAT:
75 if (av_get_packed_sample_fmt(ac->in_fmt) == in_fmt &&
76 av_get_packed_sample_fmt(ac->out_fmt) == out_fmt) {
77 ac->conv_flat = conv;
78 ac->func_descr = descr;
79 ac->ptr_align = ptr_align;
80 ac->samples_align = samples_align;
81 if (ptr_align == 1 && samples_align == 1) {
82 ac->conv_flat_generic = conv;
83 ac->func_descr_generic = descr;
84 } else {
85 ac->has_optimized_func = 1;
86 }
87 found = 1;
88 }
89 break;
90 case CONV_FUNC_TYPE_INTERLEAVE:
91 if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
92 (!channels || ac->channels == channels)) {
93 ac->conv_interleave = conv;
94 ac->func_descr = descr;
95 ac->ptr_align = ptr_align;
96 ac->samples_align = samples_align;
97 if (ptr_align == 1 && samples_align == 1) {
98 ac->conv_interleave_generic = conv;
99 ac->func_descr_generic = descr;
100 } else {
101 ac->has_optimized_func = 1;
102 }
103 found = 1;
104 }
105 break;
106 case CONV_FUNC_TYPE_DEINTERLEAVE:
107 if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
108 (!channels || ac->channels == channels)) {
109 ac->conv_deinterleave = conv;
110 ac->func_descr = descr;
111 ac->ptr_align = ptr_align;
112 ac->samples_align = samples_align;
113 if (ptr_align == 1 && samples_align == 1) {
114 ac->conv_deinterleave_generic = conv;
115 ac->func_descr_generic = descr;
116 } else {
117 ac->has_optimized_func = 1;
118 }
119 found = 1;
120 }
121 break;
122 }
123 if (found) {
124 av_log(ac->avr, AV_LOG_DEBUG, "audio_convert: found function: %-4s "
125 "to %-4s (%s)\n", av_get_sample_fmt_name(ac->in_fmt),
126 av_get_sample_fmt_name(ac->out_fmt), descr);
127 }
128}
129
130#define CONV_FUNC_NAME(dst_fmt, src_fmt) conv_ ## src_fmt ## _to_ ## dst_fmt
131
132#define CONV_LOOP(otype, expr) \
133 do { \
134 *(otype *)po = expr; \
135 pi += is; \
136 po += os; \
137 } while (po < end); \
138
139#define CONV_FUNC_FLAT(ofmt, otype, ifmt, itype, expr) \
140static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t *in, \
141 int len) \
142{ \
143 int is = sizeof(itype); \
144 int os = sizeof(otype); \
145 const uint8_t *pi = in; \
146 uint8_t *po = out; \
147 uint8_t *end = out + os * len; \
148 CONV_LOOP(otype, expr) \
149}
150
151#define CONV_FUNC_INTERLEAVE(ofmt, otype, ifmt, itype, expr) \
152static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t **in, \
153 int len, int channels) \
154{ \
155 int ch; \
156 int out_bps = sizeof(otype); \
157 int is = sizeof(itype); \
158 int os = channels * out_bps; \
159 for (ch = 0; ch < channels; ch++) { \
160 const uint8_t *pi = in[ch]; \
161 uint8_t *po = out + ch * out_bps; \
162 uint8_t *end = po + os * len; \
163 CONV_LOOP(otype, expr) \
164 } \
165}
166
167#define CONV_FUNC_DEINTERLEAVE(ofmt, otype, ifmt, itype, expr) \
168static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t **out, const uint8_t *in, \
169 int len, int channels) \
170{ \
171 int ch; \
172 int in_bps = sizeof(itype); \
173 int is = channels * in_bps; \
174 int os = sizeof(otype); \
175 for (ch = 0; ch < channels; ch++) { \
176 const uint8_t *pi = in + ch * in_bps; \
177 uint8_t *po = out[ch]; \
178 uint8_t *end = po + os * len; \
179 CONV_LOOP(otype, expr) \
180 } \
181}
182
183#define CONV_FUNC_GROUP(ofmt, otype, ifmt, itype, expr) \
184CONV_FUNC_FLAT( ofmt, otype, ifmt, itype, expr) \
185CONV_FUNC_INTERLEAVE( ofmt, otype, ifmt ## P, itype, expr) \
186CONV_FUNC_DEINTERLEAVE(ofmt ## P, otype, ifmt, itype, expr)
187
188CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_U8, uint8_t, *(const uint8_t *)pi)
189CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 8)
190CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 24)
191CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0f / (1 << 7)))
192CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0 / (1 << 7)))
193CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t, (*(const int16_t *)pi >> 8) + 0x80)
194CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi)
195CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi << 16)
196CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0f / (1 << 15)))
197CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0 / (1 << 15)))
198CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t, (*(const int32_t *)pi >> 24) + 0x80)
199CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi >> 16)
200CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi)
201CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0f / (1U << 31)))
202CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0 / (1U << 31)))
203CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8( lrintf(*(const float *)pi * (1 << 7)) + 0x80))
204CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16( lrintf(*(const float *)pi * (1 << 15))))
205CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *)pi * (1U << 31))))
206CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_FLT, float, *(const float *)pi)
207CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_FLT, float, *(const float *)pi)
208CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8( lrint(*(const double *)pi * (1 << 7)) + 0x80))
209CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16( lrint(*(const double *)pi * (1 << 15))))
210CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *)pi * (1U << 31))))
211CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_DBL, double, *(const double *)pi)
212CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_DBL, double, *(const double *)pi)
213
214#define SET_CONV_FUNC_GROUP(ofmt, ifmt) \
215ff_audio_convert_set_func(ac, ofmt, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt)); \
216ff_audio_convert_set_func(ac, ofmt ## P, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt ## P, ifmt)); \
217ff_audio_convert_set_func(ac, ofmt, ifmt ## P, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt ## P));
218
219static void set_generic_function(AudioConvert *ac)
220{
221 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8)
222 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8)
223 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8)
224 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8)
225 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8)
226 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16)
227 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16)
228 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16)
229 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16)
230 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16)
231 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32)
232 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32)
233 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32)
234 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32)
235 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32)
236 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT)
237 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT)
238 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT)
239 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT)
240 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT)
241 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL)
242 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL)
243 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL)
244 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL)
245 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL)
246}
247
248AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
249 enum AVSampleFormat out_fmt,
250 enum AVSampleFormat in_fmt,
251 int channels)
252{
253 AudioConvert *ac;
254 int in_planar, out_planar;
255
256 ac = av_mallocz(sizeof(*ac));
257 if (!ac)
258 return NULL;
259
260 ac->avr = avr;
261 ac->out_fmt = out_fmt;
262 ac->in_fmt = in_fmt;
263 ac->channels = channels;
264
265 in_planar = av_sample_fmt_is_planar(in_fmt);
266 out_planar = av_sample_fmt_is_planar(out_fmt);
267
268 if (in_planar == out_planar) {
269 ac->func_type = CONV_FUNC_TYPE_FLAT;
270 ac->planes = in_planar ? ac->channels : 1;
271 } else if (in_planar)
272 ac->func_type = CONV_FUNC_TYPE_INTERLEAVE;
273 else
274 ac->func_type = CONV_FUNC_TYPE_DEINTERLEAVE;
275
276 set_generic_function(ac);
277
278 if (ARCH_X86)
279 ff_audio_convert_init_x86(ac);
280
281 return ac;
282}
283
284int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in, int len)
285{
286 int use_generic = 1;
287
288 /* determine whether to use the optimized function based on pointer and
289 samples alignment in both the input and output */
290 if (ac->has_optimized_func) {
291 int ptr_align = FFMIN(in->ptr_align, out->ptr_align);
292 int samples_align = FFMIN(in->samples_align, out->samples_align);
293 int aligned_len = FFALIGN(len, ac->samples_align);
294 if (!(ptr_align % ac->ptr_align) && samples_align >= aligned_len) {
295 len = aligned_len;
296 use_generic = 0;
297 }
298 }
299 av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (%s)\n", len,
300 av_get_sample_fmt_name(ac->in_fmt),
301 av_get_sample_fmt_name(ac->out_fmt),
302 use_generic ? ac->func_descr_generic : ac->func_descr);
303
304 switch (ac->func_type) {
305 case CONV_FUNC_TYPE_FLAT: {
306 int p;
307 if (!in->is_planar)
308 len *= in->channels;
309 if (use_generic) {
310 for (p = 0; p < ac->planes; p++)
311 ac->conv_flat_generic(out->data[p], in->data[p], len);
312 } else {
313 for (p = 0; p < ac->planes; p++)
314 ac->conv_flat(out->data[p], in->data[p], len);
315 }
316 break;
317 }
318 case CONV_FUNC_TYPE_INTERLEAVE:
319 if (use_generic)
320 ac->conv_interleave_generic(out->data[0], in->data, len, ac->channels);
321 else
322 ac->conv_interleave(out->data[0], in->data, len, ac->channels);
323 break;
324 case CONV_FUNC_TYPE_DEINTERLEAVE:
325 if (use_generic)
326 ac->conv_deinterleave_generic(out->data, in->data[0], len, ac->channels);
327 else
328 ac->conv_deinterleave(out->data, in->data[0], len, ac->channels);
329 break;
330 }
331
332 out->nb_samples = in->nb_samples;
333 return 0;
334}
libavresample/audio_convert.h+87−0
@@ -0,0 +1,87 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_AUDIO_CONVERT_H
22#define AVRESAMPLE_AUDIO_CONVERT_H
23
24#include "libavutil/samplefmt.h"
25#include "avresample.h"
26#include "audio_data.h"
27
28typedef struct AudioConvert AudioConvert;
29
30/**
31 * Set conversion function if the parameters match.
32 *
33 * This compares the parameters of the conversion function to the parameters
34 * in the AudioConvert context. If the parameters do not match, no changes are
35 * made to the active functions. If the parameters do match and the alignment
36 * is not constrained, the function is set as the generic conversion function.
37 * If the parameters match and the alignment is constrained, the function is
38 * set as the optimized conversion function.
39 *
40 * @param ac AudioConvert context
41 * @param out_fmt output sample format
42 * @param in_fmt input sample format
43 * @param channels number of channels, or 0 for any number of channels
44 * @param ptr_align buffer pointer alignment, in bytes
45 * @param sample_align buffer size alignment, in samples
46 * @param descr function type description (e.g. "C" or "SSE")
47 * @param conv conversion function pointer
48 */
49void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt,
50 enum AVSampleFormat in_fmt, int channels,
51 int ptr_align, int samples_align,
52 const char *descr, void *conv);
53
54/**
55 * Allocate and initialize AudioConvert context for sample format conversion.
56 *
57 * @param avr AVAudioResampleContext
58 * @param out_fmt output sample format
59 * @param in_fmt input sample format
60 * @param channels number of channels
61 * @return newly-allocated AudioConvert context
62 */
63AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
64 enum AVSampleFormat out_fmt,
65 enum AVSampleFormat in_fmt,
66 int channels);
67
68/**
69 * Convert audio data from one sample format to another.
70 *
71 * For each call, the alignment of the input and output AudioData buffers are
72 * examined to determine whether to use the generic or optimized conversion
73 * function (when available).
74 *
75 * @param ac AudioConvert context
76 * @param out output audio data
77 * @param in input audio data
78 * @param len number of samples to convert
79 * @return 0 on success, negative AVERROR code on failure
80 */
81int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in, int len);
82
83/* arch-specific initialization functions */
84
85void ff_audio_convert_init_x86(AudioConvert *ac);
86
87#endif /* AVRESAMPLE_AUDIO_CONVERT_H */
libavresample/audio_data.c+345−0
@@ -0,0 +1,345 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stdint.h>
22
23#include "libavutil/mem.h"
24#include "audio_data.h"
25
26static const AVClass audio_data_class = {
27 .class_name = "AudioData",
28 .item_name = av_default_item_name,
29 .version = LIBAVUTIL_VERSION_INT,
30};
31
32/*
33 * Calculate alignment for data pointers.
34 */
35static void calc_ptr_alignment(AudioData *a)
36{
37 int p;
38 int min_align = 128;
39
40 for (p = 0; p < a->planes; p++) {
41 int cur_align = 128;
42 while ((intptr_t)a->data[p] % cur_align)
43 cur_align >>= 1;
44 if (cur_align < min_align)
45 min_align = cur_align;
46 }
47 a->ptr_align = min_align;
48}
49
50int ff_audio_data_set_channels(AudioData *a, int channels)
51{
52 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
53 channels > a->allocated_channels)
54 return AVERROR(EINVAL);
55
56 a->channels = channels;
57 a->planes = a->is_planar ? channels : 1;
58
59 calc_ptr_alignment(a);
60
61 return 0;
62}
63
64int ff_audio_data_init(AudioData *a, void **src, int plane_size, int channels,
65 int nb_samples, enum AVSampleFormat sample_fmt,
66 int read_only, const char *name)
67{
68 int p;
69
70 memset(a, 0, sizeof(*a));
71 a->class = &audio_data_class;
72
73 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
74 av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
75 return AVERROR(EINVAL);
76 }
77
78 a->sample_size = av_get_bytes_per_sample(sample_fmt);
79 if (!a->sample_size) {
80 av_log(a, AV_LOG_ERROR, "invalid sample format\n");
81 return AVERROR(EINVAL);
82 }
83 a->is_planar = av_sample_fmt_is_planar(sample_fmt);
84 a->planes = a->is_planar ? channels : 1;
85 a->stride = a->sample_size * (a->is_planar ? 1 : channels);
86
87 for (p = 0; p < (a->is_planar ? channels : 1); p++) {
88 if (!src[p]) {
89 av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
90 return AVERROR(EINVAL);
91 }
92 a->data[p] = src[p];
93 }
94 a->allocated_samples = nb_samples * !read_only;
95 a->nb_samples = nb_samples;
96 a->sample_fmt = sample_fmt;
97 a->channels = channels;
98 a->allocated_channels = channels;
99 a->read_only = read_only;
100 a->allow_realloc = 0;
101 a->name = name ? name : "{no name}";
102
103 calc_ptr_alignment(a);
104 a->samples_align = plane_size / a->stride;
105
106 return 0;
107}
108
109AudioData *ff_audio_data_alloc(int channels, int nb_samples,
110 enum AVSampleFormat sample_fmt, const char *name)
111{
112 AudioData *a;
113 int ret;
114
115 if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
116 return NULL;
117
118 a = av_mallocz(sizeof(*a));
119 if (!a)
120 return NULL;
121
122 a->sample_size = av_get_bytes_per_sample(sample_fmt);
123 if (!a->sample_size) {
124 av_free(a);
125 return NULL;
126 }
127 a->is_planar = av_sample_fmt_is_planar(sample_fmt);
128 a->planes = a->is_planar ? channels : 1;
129 a->stride = a->sample_size * (a->is_planar ? 1 : channels);
130
131 a->class = &audio_data_class;
132 a->sample_fmt = sample_fmt;
133 a->channels = channels;
134 a->allocated_channels = channels;
135 a->read_only = 0;
136 a->allow_realloc = 1;
137 a->name = name ? name : "{no name}";
138
139 if (nb_samples > 0) {
140 ret = ff_audio_data_realloc(a, nb_samples);
141 if (ret < 0) {
142 av_free(a);
143 return NULL;
144 }
145 return a;
146 } else {
147 calc_ptr_alignment(a);
148 return a;
149 }
150}
151
152int ff_audio_data_realloc(AudioData *a, int nb_samples)
153{
154 int ret, new_buf_size, plane_size, p;
155
156 /* check if buffer is already large enough */
157 if (a->allocated_samples >= nb_samples)
158 return 0;
159
160 /* validate that the output is not read-only and realloc is allowed */
161 if (a->read_only || !a->allow_realloc)
162 return AVERROR(EINVAL);
163
164 new_buf_size = av_samples_get_buffer_size(&plane_size,
165 a->allocated_channels, nb_samples,
166 a->sample_fmt, 0);
167 if (new_buf_size < 0)
168 return new_buf_size;
169
170 /* if there is already data in the buffer and the sample format is planar,
171 allocate a new buffer and copy the data, otherwise just realloc the
172 internal buffer and set new data pointers */
173 if (a->nb_samples > 0 && a->is_planar) {
174 uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
175
176 ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
177 nb_samples, a->sample_fmt, 0);
178 if (ret < 0)
179 return ret;
180
181 for (p = 0; p < a->planes; p++)
182 memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
183
184 av_freep(&a->buffer);
185 memcpy(a->data, new_data, sizeof(new_data));
186 a->buffer = a->data[0];
187 } else {
188 av_freep(&a->buffer);
189 a->buffer = av_malloc(new_buf_size);
190 if (!a->buffer)
191 return AVERROR(ENOMEM);
192 ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
193 a->allocated_channels, nb_samples,
194 a->sample_fmt, 0);
195 if (ret < 0)
196 return ret;
197 }
198 a->buffer_size = new_buf_size;
199 a->allocated_samples = nb_samples;
200
201 calc_ptr_alignment(a);
202 a->samples_align = plane_size / a->stride;
203
204 return 0;
205}
206
207void ff_audio_data_free(AudioData **a)
208{
209 if (!*a)
210 return;
211 av_free((*a)->buffer);
212 av_freep(a);
213}
214
215int ff_audio_data_copy(AudioData *dst, AudioData *src)
216{
217 int ret, p;
218
219 /* validate input/output compatibility */
220 if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
221 return AVERROR(EINVAL);
222
223 /* if the input is empty, just empty the output */
224 if (!src->nb_samples) {
225 dst->nb_samples = 0;
226 return 0;
227 }
228
229 /* reallocate output if necessary */
230 ret = ff_audio_data_realloc(dst, src->nb_samples);
231 if (ret < 0)
232 return ret;
233
234 /* copy data */
235 for (p = 0; p < src->planes; p++)
236 memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
237 dst->nb_samples = src->nb_samples;
238
239 return 0;
240}
241
242int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
243 int src_offset, int nb_samples)
244{
245 int ret, p, dst_offset2, dst_move_size;
246
247 /* validate input/output compatibility */
248 if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
249 av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
250 return AVERROR(EINVAL);
251 }
252
253 /* validate offsets are within the buffer bounds */
254 if (dst_offset < 0 || dst_offset > dst->nb_samples ||
255 src_offset < 0 || src_offset > src->nb_samples) {
256 av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
257 src_offset, dst_offset);
258 return AVERROR(EINVAL);
259 }
260
261 /* check offsets and sizes to see if we can just do nothing and return */
262 if (nb_samples > src->nb_samples - src_offset)
263 nb_samples = src->nb_samples - src_offset;
264 if (nb_samples <= 0)
265 return 0;
266
267 /* validate that the output is not read-only */
268 if (dst->read_only) {
269 av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
270 return AVERROR(EINVAL);
271 }
272
273 /* reallocate output if necessary */
274 ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
275 if (ret < 0) {
276 av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
277 return ret;
278 }
279
280 dst_offset2 = dst_offset + nb_samples;
281 dst_move_size = dst->nb_samples - dst_offset;
282
283 for (p = 0; p < src->planes; p++) {
284 if (dst_move_size > 0) {
285 memmove(dst->data[p] + dst_offset2 * dst->stride,
286 dst->data[p] + dst_offset * dst->stride,
287 dst_move_size * dst->stride);
288 }
289 memcpy(dst->data[p] + dst_offset * dst->stride,
290 src->data[p] + src_offset * src->stride,
291 nb_samples * src->stride);
292 }
293 dst->nb_samples += nb_samples;
294
295 return 0;
296}
297
298void ff_audio_data_drain(AudioData *a, int nb_samples)
299{
300 if (a->nb_samples <= nb_samples) {
301 /* drain the whole buffer */
302 a->nb_samples = 0;
303 } else {
304 int p;
305 int move_offset = a->stride * nb_samples;
306 int move_size = a->stride * (a->nb_samples - nb_samples);
307
308 for (p = 0; p < a->planes; p++)
309 memmove(a->data[p], a->data[p] + move_offset, move_size);
310
311 a->nb_samples -= nb_samples;
312 }
313}
314
315int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
316 int nb_samples)
317{
318 uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
319 int offset_size, p;
320
321 if (offset >= a->nb_samples)
322 return 0;
323 offset_size = offset * a->stride;
324 for (p = 0; p < a->planes; p++)
325 offset_data[p] = a->data[p] + offset_size;
326
327 return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
328}
329
330int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
331{
332 int ret;
333
334 if (a->read_only)
335 return AVERROR(EINVAL);
336
337 ret = ff_audio_data_realloc(a, nb_samples);
338 if (ret < 0)
339 return ret;
340
341 ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
342 if (ret >= 0)
343 a->nb_samples = ret;
344 return ret;
345}
libavresample/audio_data.h+173−0
@@ -0,0 +1,173 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_AUDIO_DATA_H
22#define AVRESAMPLE_AUDIO_DATA_H
23
24#include <stdint.h>
25
26#include "libavutil/audio_fifo.h"
27#include "libavutil/log.h"
28#include "libavutil/samplefmt.h"
29#include "avresample.h"
30
31/**
32 * Audio buffer used for intermediate storage between conversion phases.
33 */
34typedef struct AudioData {
35 const AVClass *class; /**< AVClass for logging */
36 uint8_t *data[AVRESAMPLE_MAX_CHANNELS]; /**< data plane pointers */
37 uint8_t *buffer; /**< data buffer */
38 unsigned int buffer_size; /**< allocated buffer size */
39 int allocated_samples; /**< number of samples the buffer can hold */
40 int nb_samples; /**< current number of samples */
41 enum AVSampleFormat sample_fmt; /**< sample format */
42 int channels; /**< channel count */
43 int allocated_channels; /**< allocated channel count */
44 int is_planar; /**< sample format is planar */
45 int planes; /**< number of data planes */
46 int sample_size; /**< bytes per sample */
47 int stride; /**< sample byte offset within a plane */
48 int read_only; /**< data is read-only */
49 int allow_realloc; /**< realloc is allowed */
50 int ptr_align; /**< minimum data pointer alignment */
51 int samples_align; /**< allocated samples alignment */
52 const char *name; /**< name for debug logging */
53} AudioData;
54
55int ff_audio_data_set_channels(AudioData *a, int channels);
56
57/**
58 * Initialize AudioData using a given source.
59 *
60 * This does not allocate an internal buffer. It only sets the data pointers
61 * and audio parameters.
62 *
63 * @param a AudioData struct
64 * @param src source data pointers
65 * @param plane_size plane size, in bytes.
66 * This can be 0 if unknown, but that will lead to
67 * optimized functions not being used in many cases,
68 * which could slow down some conversions.
69 * @param channels channel count
70 * @param nb_samples number of samples in the source data
71 * @param sample_fmt sample format
72 * @param read_only indicates if buffer is read only or read/write
73 * @param name name for debug logging (can be NULL)
74 * @return 0 on success, negative AVERROR value on error
75 */
76int ff_audio_data_init(AudioData *a, void **src, int plane_size, int channels,
77 int nb_samples, enum AVSampleFormat sample_fmt,
78 int read_only, const char *name);
79
80/**
81 * Allocate AudioData.
82 *
83 * This allocates an internal buffer and sets audio parameters.
84 *
85 * @param channels channel count
86 * @param nb_samples number of samples to allocate space for
87 * @param sample_fmt sample format
88 * @param name name for debug logging (can be NULL)
89 * @return newly allocated AudioData struct, or NULL on error
90 */
91AudioData *ff_audio_data_alloc(int channels, int nb_samples,
92 enum AVSampleFormat sample_fmt,
93 const char *name);
94
95/**
96 * Reallocate AudioData.
97 *
98 * The AudioData must have been previously allocated with ff_audio_data_alloc().
99 *
100 * @param a AudioData struct
101 * @param nb_samples number of samples to allocate space for
102 * @return 0 on success, negative AVERROR value on error
103 */
104int ff_audio_data_realloc(AudioData *a, int nb_samples);
105
106/**
107 * Free AudioData.
108 *
109 * The AudioData must have been previously allocated with ff_audio_data_alloc().
110 *
111 * @param a AudioData struct
112 */
113void ff_audio_data_free(AudioData **a);
114
115/**
116 * Copy data from one AudioData to another.
117 *
118 * @param out output AudioData
119 * @param in input AudioData
120 * @return 0 on success, negative AVERROR value on error
121 */
122int ff_audio_data_copy(AudioData *out, AudioData *in);
123
124/**
125 * Append data from one AudioData to the end of another.
126 *
127 * @param dst destination AudioData
128 * @param dst_offset offset, in samples, to start writing, relative to the
129 * start of dst
130 * @param src source AudioData
131 * @param src_offset offset, in samples, to start copying, relative to the
132 * start of the src
133 * @param nb_samples number of samples to copy
134 * @return 0 on success, negative AVERROR value on error
135 */
136int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
137 int src_offset, int nb_samples);
138
139/**
140 * Drain samples from the start of the AudioData.
141 *
142 * Remaining samples are shifted to the start of the AudioData.
143 *
144 * @param a AudioData struct
145 * @param nb_samples number of samples to drain
146 */
147void ff_audio_data_drain(AudioData *a, int nb_samples);
148
149/**
150 * Add samples in AudioData to an AVAudioFifo.
151 *
152 * @param af Audio FIFO Buffer
153 * @param a AudioData struct
154 * @param offset number of samples to skip from the start of the data
155 * @param nb_samples number of samples to add to the FIFO
156 * @return number of samples actually added to the FIFO, or
157 * negative AVERROR code on error
158 */
159int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
160 int nb_samples);
161
162/**
163 * Read samples from an AVAudioFifo to AudioData.
164 *
165 * @param af Audio FIFO Buffer
166 * @param a AudioData struct
167 * @param nb_samples number of samples to read from the FIFO
168 * @return number of samples actually read from the FIFO, or
169 * negative AVERROR code on error
170 */
171int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples);
172
173#endif /* AVRESAMPLE_AUDIO_DATA_H */
libavresample/audio_mix.c+356−0
@@ -0,0 +1,356 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stdint.h>
22
23#include "libavutil/libm.h"
24#include "libavutil/samplefmt.h"
25#include "avresample.h"
26#include "internal.h"
27#include "audio_data.h"
28#include "audio_mix.h"
29
30static const char *coeff_type_names[] = { "q6", "q15", "flt" };
31
32void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
33 enum AVMixCoeffType coeff_type, int in_channels,
34 int out_channels, int ptr_align, int samples_align,
35 const char *descr, void *mix_func)
36{
37 if (fmt == am->fmt && coeff_type == am->coeff_type &&
38 ( in_channels == am->in_channels || in_channels == 0) &&
39 (out_channels == am->out_channels || out_channels == 0)) {
40 char chan_str[16];
41 am->mix = mix_func;
42 am->func_descr = descr;
43 am->ptr_align = ptr_align;
44 am->samples_align = samples_align;
45 if (ptr_align == 1 && samples_align == 1) {
46 am->mix_generic = mix_func;
47 am->func_descr_generic = descr;
48 } else {
49 am->has_optimized_func = 1;
50 }
51 if (in_channels) {
52 if (out_channels)
53 snprintf(chan_str, sizeof(chan_str), "[%d to %d] ",
54 in_channels, out_channels);
55 else
56 snprintf(chan_str, sizeof(chan_str), "[%d to any] ",
57 in_channels);
58 } else if (out_channels) {
59 snprintf(chan_str, sizeof(chan_str), "[any to %d] ",
60 out_channels);
61 }
62 av_log(am->avr, AV_LOG_DEBUG, "audio_mix: found function: [fmt=%s] "
63 "[c=%s] %s(%s)\n", av_get_sample_fmt_name(fmt),
64 coeff_type_names[coeff_type],
65 (in_channels || out_channels) ? chan_str : "", descr);
66 }
67}
68
69#define MIX_FUNC_NAME(fmt, cfmt) mix_any_ ## fmt ##_## cfmt ##_c
70
71#define MIX_FUNC_GENERIC(fmt, cfmt, stype, ctype, sumtype, expr) \
72static void MIX_FUNC_NAME(fmt, cfmt)(stype **samples, ctype **matrix, \
73 int len, int out_ch, int in_ch) \
74{ \
75 int i, in, out; \
76 stype temp[AVRESAMPLE_MAX_CHANNELS]; \
77 for (i = 0; i < len; i++) { \
78 for (out = 0; out < out_ch; out++) { \
79 sumtype sum = 0; \
80 for (in = 0; in < in_ch; in++) \
81 sum += samples[in][i] * matrix[out][in]; \
82 temp[out] = expr; \
83 } \
84 for (out = 0; out < out_ch; out++) \
85 samples[out][i] = temp[out]; \
86 } \
87}
88
89MIX_FUNC_GENERIC(FLTP, FLT, float, float, float, sum)
90MIX_FUNC_GENERIC(S16P, FLT, int16_t, float, float, av_clip_int16(lrintf(sum)))
91MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15))
92MIX_FUNC_GENERIC(S16P, Q6, int16_t, int16_t, int32_t, av_clip_int16(sum >> 6))
93
94/* TODO: templatize the channel-specific C functions */
95
96static void mix_2_to_1_fltp_flt_c(float **samples, float **matrix, int len,
97 int out_ch, int in_ch)
98{
99 float *src0 = samples[0];
100 float *src1 = samples[1];
101 float *dst = src0;
102 float m0 = matrix[0][0];
103 float m1 = matrix[0][1];
104
105 while (len > 4) {
106 *dst++ = *src0++ * m0 + *src1++ * m1;
107 *dst++ = *src0++ * m0 + *src1++ * m1;
108 *dst++ = *src0++ * m0 + *src1++ * m1;
109 *dst++ = *src0++ * m0 + *src1++ * m1;
110 len -= 4;
111 }
112 while (len > 0) {
113 *dst++ = *src0++ * m0 + *src1++ * m1;
114 len--;
115 }
116}
117
118static void mix_1_to_2_fltp_flt_c(float **samples, float **matrix, int len,
119 int out_ch, int in_ch)
120{
121 float v;
122 float *dst0 = samples[0];
123 float *dst1 = samples[1];
124 float *src = dst0;
125 float m0 = matrix[0][0];
126 float m1 = matrix[1][0];
127
128 while (len > 4) {
129 v = *src++;
130 *dst0++ = v * m1;
131 *dst1++ = v * m0;
132 v = *src++;
133 *dst0++ = v * m1;
134 *dst1++ = v * m0;
135 v = *src++;
136 *dst0++ = v * m1;
137 *dst1++ = v * m0;
138 v = *src++;
139 *dst0++ = v * m1;
140 *dst1++ = v * m0;
141 len -= 4;
142 }
143 while (len > 0) {
144 v = *src++;
145 *dst0++ = v * m1;
146 *dst1++ = v * m0;
147 len--;
148 }
149}
150
151static void mix_6_to_2_fltp_flt_c(float **samples, float **matrix, int len,
152 int out_ch, int in_ch)
153{
154 float v0, v1;
155 float *src0 = samples[0];
156 float *src1 = samples[1];
157 float *src2 = samples[2];
158 float *src3 = samples[3];
159 float *src4 = samples[4];
160 float *src5 = samples[5];
161 float *dst0 = src0;
162 float *dst1 = src1;
163 float *m0 = matrix[0];
164 float *m1 = matrix[1];
165
166 while (len > 0) {
167 v0 = *src0++;
168 v1 = *src1++;
169 *dst0++ = v0 * m0[0] +
170 v1 * m0[1] +
171 *src2 * m0[2] +
172 *src3 * m0[3] +
173 *src4 * m0[4] +
174 *src5 * m0[5];
175 *dst1++ = v0 * m1[0] +
176 v1 * m1[1] +
177 *src2++ * m1[2] +
178 *src3++ * m1[3] +
179 *src4++ * m1[4] +
180 *src5++ * m1[5];
181 len--;
182 }
183}
184
185static void mix_2_to_6_fltp_flt_c(float **samples, float **matrix, int len,
186 int out_ch, int in_ch)
187{
188 float v0, v1;
189 float *dst0 = samples[0];
190 float *dst1 = samples[1];
191 float *dst2 = samples[2];
192 float *dst3 = samples[3];
193 float *dst4 = samples[4];
194 float *dst5 = samples[5];
195 float *src0 = dst0;
196 float *src1 = dst1;
197
198 while (len > 0) {
199 v0 = *src0++;
200 v1 = *src1++;
201 *dst0++ = v0 * matrix[0][0] + v1 * matrix[0][1];
202 *dst1++ = v0 * matrix[1][0] + v1 * matrix[1][1];
203 *dst2++ = v0 * matrix[2][0] + v1 * matrix[2][1];
204 *dst3++ = v0 * matrix[3][0] + v1 * matrix[3][1];
205 *dst4++ = v0 * matrix[4][0] + v1 * matrix[4][1];
206 *dst5++ = v0 * matrix[5][0] + v1 * matrix[5][1];
207 len--;
208 }
209}
210
211static int mix_function_init(AudioMix *am)
212{
213 /* any-to-any C versions */
214
215 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
216 0, 0, 1, 1, "C", MIX_FUNC_NAME(FLTP, FLT));
217
218 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
219 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, FLT));
220
221 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q15,
222 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q15));
223
224 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q6,
225 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q6));
226
227 /* channel-specific C versions */
228
229 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
230 2, 1, 1, 1, "C", mix_2_to_1_fltp_flt_c);
231
232 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
233 1, 2, 1, 1, "C", mix_1_to_2_fltp_flt_c);
234
235 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
236 6, 2, 1, 1, "C", mix_6_to_2_fltp_flt_c);
237
238 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
239 2, 6, 1, 1, "C", mix_2_to_6_fltp_flt_c);
240
241 if (ARCH_X86)
242 ff_audio_mix_init_x86(am);
243
244 if (!am->mix) {
245 av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
246 "[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
247 coeff_type_names[am->coeff_type], am->in_channels,
248 am->out_channels);
249 return AVERROR_PATCHWELCOME;
250 }
251 return 0;
252}
253
254int ff_audio_mix_init(AVAudioResampleContext *avr)
255{
256 int ret;
257
258 /* build matrix if the user did not already set one */
259 if (!avr->am->matrix) {
260 int i, j;
261 char in_layout_name[128];
262 char out_layout_name[128];
263 double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
264 sizeof(*matrix_dbl));
265 if (!matrix_dbl)
266 return AVERROR(ENOMEM);
267
268 ret = avresample_build_matrix(avr->in_channel_layout,
269 avr->out_channel_layout,
270 avr->center_mix_level,
271 avr->surround_mix_level,
272 avr->lfe_mix_level, 1, matrix_dbl,
273 avr->in_channels);
274 if (ret < 0) {
275 av_free(matrix_dbl);
276 return ret;
277 }
278
279 av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
280 avr->in_channels, avr->in_channel_layout);
281 av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
282 avr->out_channels, avr->out_channel_layout);
283 av_log(avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
284 in_layout_name, out_layout_name);
285 for (i = 0; i < avr->out_channels; i++) {
286 for (j = 0; j < avr->in_channels; j++) {
287 av_log(avr, AV_LOG_DEBUG, " %0.3f ",
288 matrix_dbl[i * avr->in_channels + j]);
289 }
290 av_log(avr, AV_LOG_DEBUG, "\n");
291 }
292
293 ret = avresample_set_matrix(avr, matrix_dbl, avr->in_channels);
294 if (ret < 0) {
295 av_free(matrix_dbl);
296 return ret;
297 }
298 av_free(matrix_dbl);
299 }
300
301 avr->am->fmt = avr->internal_sample_fmt;
302 avr->am->coeff_type = avr->mix_coeff_type;
303 avr->am->in_layout = avr->in_channel_layout;
304 avr->am->out_layout = avr->out_channel_layout;
305 avr->am->in_channels = avr->in_channels;
306 avr->am->out_channels = avr->out_channels;
307
308 ret = mix_function_init(avr->am);
309 if (ret < 0)
310 return ret;
311
312 return 0;
313}
314
315void ff_audio_mix_close(AudioMix *am)
316{
317 if (!am)
318 return;
319 if (am->matrix) {
320 av_free(am->matrix[0]);
321 am->matrix = NULL;
322 }
323 memset(am->matrix_q6, 0, sizeof(am->matrix_q6 ));
324 memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
325 memset(am->matrix_flt, 0, sizeof(am->matrix_flt));
326}
327
328int ff_audio_mix(AudioMix *am, AudioData *src)
329{
330 int use_generic = 1;
331 int len = src->nb_samples;
332
333 /* determine whether to use the optimized function based on pointer and
334 samples alignment in both the input and output */
335 if (am->has_optimized_func) {
336 int aligned_len = FFALIGN(len, am->samples_align);
337 if (!(src->ptr_align % am->ptr_align) &&
338 src->samples_align >= aligned_len) {
339 len = aligned_len;
340 use_generic = 0;
341 }
342 }
343 av_dlog(am->avr, "audio_mix: %d samples - %d to %d channels (%s)\n",
344 src->nb_samples, am->in_channels, am->out_channels,
345 use_generic ? am->func_descr_generic : am->func_descr);
346
347 if (use_generic)
348 am->mix_generic(src->data, am->matrix, len, am->out_channels,
349 am->in_channels);
350 else
351 am->mix(src->data, am->matrix, len, am->out_channels, am->in_channels);
352
353 ff_audio_data_set_channels(src, am->out_channels);
354
355 return 0;
356}
libavresample/audio_mix.h+108−0
@@ -0,0 +1,108 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_AUDIO_MIX_H
22#define AVRESAMPLE_AUDIO_MIX_H
23
24#include <stdint.h>
25
26#include "libavutil/samplefmt.h"
27#include "avresample.h"
28#include "audio_data.h"
29
30typedef void (mix_func)(uint8_t **src, void **matrix, int len, int out_ch,
31 int in_ch);
32
33typedef struct AudioMix {
34 AVAudioResampleContext *avr;
35 enum AVSampleFormat fmt;
36 enum AVMixCoeffType coeff_type;
37 uint64_t in_layout;
38 uint64_t out_layout;
39 int in_channels;
40 int out_channels;
41
42 int ptr_align;
43 int samples_align;
44 int has_optimized_func;
45 const char *func_descr;
46 const char *func_descr_generic;
47 mix_func *mix;
48 mix_func *mix_generic;
49
50 int16_t *matrix_q6[AVRESAMPLE_MAX_CHANNELS];
51 int32_t *matrix_q15[AVRESAMPLE_MAX_CHANNELS];
52 float *matrix_flt[AVRESAMPLE_MAX_CHANNELS];
53 void **matrix;
54} AudioMix;
55
56/**
57 * Set mixing function if the parameters match.
58 *
59 * This compares the parameters of the mixing function to the parameters in the
60 * AudioMix context. If the parameters do not match, no changes are made to the
61 * active functions. If the parameters do match and the alignment is not
62 * constrained, the function is set as the generic mixing function. If the
63 * parameters match and the alignment is constrained, the function is set as
64 * the optimized mixing function.
65 *
66 * @param am AudioMix context
67 * @param fmt input/output sample format
68 * @param coeff_type mixing coefficient type
69 * @param in_channels number of input channels, or 0 for any number of channels
70 * @param out_channels number of output channels, or 0 for any number of channels
71 * @param ptr_align buffer pointer alignment, in bytes
72 * @param sample_align buffer size alignment, in samples
73 * @param descr function type description (e.g. "C" or "SSE")
74 * @param mix_func mixing function pointer
75 */
76void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
77 enum AVMixCoeffType coeff_type, int in_channels,
78 int out_channels, int ptr_align, int samples_align,
79 const char *descr, void *mix_func);
80
81/**
82 * Initialize the AudioMix context in the AVAudioResampleContext.
83 *
84 * The parameters in the AVAudioResampleContext are used to initialize the
85 * AudioMix context and set the mixing matrix.
86 *
87 * @param avr AVAudioResampleContext
88 * @return 0 on success, negative AVERROR code on failure
89 */
90int ff_audio_mix_init(AVAudioResampleContext *avr);
91
92/**
93 * Close an AudioMix context.
94 *
95 * This clears and frees the mixing matrix arrays.
96 */
97void ff_audio_mix_close(AudioMix *am);
98
99/**
100 * Apply channel mixing to audio data using the current mixing matrix.
101 */
102int ff_audio_mix(AudioMix *am, AudioData *src);
103
104/* arch-specific initialization functions */
105
106void ff_audio_mix_init_x86(AudioMix *am);
107
108#endif /* AVRESAMPLE_AUDIO_MIX_H */
libavresample/audio_mix_matrix.c+346−0
@@ -0,0 +1,346 @@
1/*
2 * Copyright (C) 2011 Michael Niedermayer (michaelni@gmx.at)
3 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 *
5 * This file is part of Libav.
6 *
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdint.h>
23
24#include "libavutil/libm.h"
25#include "libavutil/samplefmt.h"
26#include "avresample.h"
27#include "internal.h"
28#include "audio_data.h"
29#include "audio_mix.h"
30
31/* channel positions */
32#define FRONT_LEFT 0
33#define FRONT_RIGHT 1
34#define FRONT_CENTER 2
35#define LOW_FREQUENCY 3
36#define BACK_LEFT 4
37#define BACK_RIGHT 5
38#define FRONT_LEFT_OF_CENTER 6
39#define FRONT_RIGHT_OF_CENTER 7
40#define BACK_CENTER 8
41#define SIDE_LEFT 9
42#define SIDE_RIGHT 10
43#define TOP_CENTER 11
44#define TOP_FRONT_LEFT 12
45#define TOP_FRONT_CENTER 13
46#define TOP_FRONT_RIGHT 14
47#define TOP_BACK_LEFT 15
48#define TOP_BACK_CENTER 16
49#define TOP_BACK_RIGHT 17
50#define STEREO_LEFT 29
51#define STEREO_RIGHT 30
52#define WIDE_LEFT 31
53#define WIDE_RIGHT 32
54#define SURROUND_DIRECT_LEFT 33
55#define SURROUND_DIRECT_RIGHT 34
56
57static av_always_inline int even(uint64_t layout)
58{
59 return (!layout || (layout & (layout - 1)));
60}
61
62static int sane_layout(uint64_t layout)
63{
64 /* check that there is at least 1 front speaker */
65 if (!(layout & AV_CH_LAYOUT_SURROUND))
66 return 0;
67
68 /* check for left/right symmetry */
69 if (!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)) ||
70 !even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)) ||
71 !even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)) ||
72 !even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)) ||
73 !even(layout & (AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT)) ||
74 !even(layout & (AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT)) ||
75 !even(layout & (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT)) ||
76 !even(layout & (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT)) ||
77 !even(layout & (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT)))
78 return 0;
79
80 return 1;
81}
82
83int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
84 double center_mix_level, double surround_mix_level,
85 double lfe_mix_level, int normalize,
86 double *matrix_out, int stride)
87{
88 int i, j, out_i, out_j;
89 double matrix[64][64] = {{0}};
90 int64_t unaccounted = in_layout & ~out_layout;
91 double maxcoef = 0;
92 int in_channels, out_channels;
93
94 in_channels = av_get_channel_layout_nb_channels( in_layout);
95 out_channels = av_get_channel_layout_nb_channels(out_layout);
96
97 memset(matrix_out, 0, out_channels * stride * sizeof(*matrix_out));
98
99 /* check if layouts are supported */
100 if (!in_layout || in_channels > AVRESAMPLE_MAX_CHANNELS)
101 return AVERROR(EINVAL);
102 if (!out_layout || out_channels > AVRESAMPLE_MAX_CHANNELS)
103 return AVERROR(EINVAL);
104
105 /* check if layouts are unbalanced or abnormal */
106 if (!sane_layout(in_layout) || !sane_layout(out_layout))
107 return AVERROR_PATCHWELCOME;
108
109 /* route matching input/output channels */
110 for (i = 0; i < 64; i++) {
111 if (in_layout & out_layout & (1ULL << i))
112 matrix[i][i] = 1.0;
113 }
114
115 /* mix front center to front left/right */
116 if (unaccounted & AV_CH_FRONT_CENTER) {
117 if ((out_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) {
118 matrix[FRONT_LEFT ][FRONT_CENTER] += M_SQRT1_2;
119 matrix[FRONT_RIGHT][FRONT_CENTER] += M_SQRT1_2;
120 } else
121 return AVERROR_PATCHWELCOME;
122 }
123 /* mix front left/right to center */
124 if (unaccounted & AV_CH_LAYOUT_STEREO) {
125 if (out_layout & AV_CH_FRONT_CENTER) {
126 matrix[FRONT_CENTER][FRONT_LEFT ] += M_SQRT1_2;
127 matrix[FRONT_CENTER][FRONT_RIGHT] += M_SQRT1_2;
128 /* mix left/right/center to center */
129 if (in_layout & AV_CH_FRONT_CENTER)
130 matrix[FRONT_CENTER][FRONT_CENTER] = center_mix_level * M_SQRT2;
131 } else
132 return AVERROR_PATCHWELCOME;
133 }
134 /* mix back center to back, side, or front */
135 if (unaccounted & AV_CH_BACK_CENTER) {
136 if (out_layout & AV_CH_BACK_LEFT) {
137 matrix[BACK_LEFT ][BACK_CENTER] += M_SQRT1_2;
138 matrix[BACK_RIGHT][BACK_CENTER] += M_SQRT1_2;
139 } else if (out_layout & AV_CH_SIDE_LEFT) {
140 matrix[SIDE_LEFT ][BACK_CENTER] += M_SQRT1_2;
141 matrix[SIDE_RIGHT][BACK_CENTER] += M_SQRT1_2;
142 } else if (out_layout & AV_CH_FRONT_LEFT) {
143 matrix[FRONT_LEFT ][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
144 matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
145 } else if (out_layout & AV_CH_FRONT_CENTER) {
146 matrix[FRONT_CENTER][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
147 } else
148 return AVERROR_PATCHWELCOME;
149 }
150 /* mix back left/right to back center, side, or front */
151 if (unaccounted & AV_CH_BACK_LEFT) {
152 if (out_layout & AV_CH_BACK_CENTER) {
153 matrix[BACK_CENTER][BACK_LEFT ] += M_SQRT1_2;
154 matrix[BACK_CENTER][BACK_RIGHT] += M_SQRT1_2;
155 } else if (out_layout & AV_CH_SIDE_LEFT) {
156 /* if side channels do not exist in the input, just copy back
157 channels to side channels, otherwise mix back into side */
158 if (in_layout & AV_CH_SIDE_LEFT) {
159 matrix[SIDE_LEFT ][BACK_LEFT ] += M_SQRT1_2;
160 matrix[SIDE_RIGHT][BACK_RIGHT] += M_SQRT1_2;
161 } else {
162 matrix[SIDE_LEFT ][BACK_LEFT ] += 1.0;
163 matrix[SIDE_RIGHT][BACK_RIGHT] += 1.0;
164 }
165 } else if (out_layout & AV_CH_FRONT_LEFT) {
166 matrix[FRONT_LEFT ][BACK_LEFT ] += surround_mix_level;
167 matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
168 } else if (out_layout & AV_CH_FRONT_CENTER) {
169 matrix[FRONT_CENTER][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
170 matrix[FRONT_CENTER][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
171 } else
172 return AVERROR_PATCHWELCOME;
173 }
174 /* mix side left/right into back or front */
175 if (unaccounted & AV_CH_SIDE_LEFT) {
176 if (out_layout & AV_CH_BACK_LEFT) {
177 /* if back channels do not exist in the input, just copy side
178 channels to back channels, otherwise mix side into back */
179 if (in_layout & AV_CH_BACK_LEFT) {
180 matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
181 matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
182 } else {
183 matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
184 matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
185 }
186 } else if (out_layout & AV_CH_BACK_CENTER) {
187 matrix[BACK_CENTER][SIDE_LEFT ] += M_SQRT1_2;
188 matrix[BACK_CENTER][SIDE_RIGHT] += M_SQRT1_2;
189 } else if (out_layout & AV_CH_FRONT_LEFT) {
190 matrix[FRONT_LEFT ][SIDE_LEFT ] += surround_mix_level;
191 matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
192 } else if (out_layout & AV_CH_FRONT_CENTER) {
193 matrix[FRONT_CENTER][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
194 matrix[FRONT_CENTER][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
195 } else
196 return AVERROR_PATCHWELCOME;
197 }
198 /* mix left-of-center/right-of-center into front left/right or center */
199 if (unaccounted & AV_CH_FRONT_LEFT_OF_CENTER) {
200 if (out_layout & AV_CH_FRONT_LEFT) {
201 matrix[FRONT_LEFT ][FRONT_LEFT_OF_CENTER ] += 1.0;
202 matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER] += 1.0;
203 } else if (out_layout & AV_CH_FRONT_CENTER) {
204 matrix[FRONT_CENTER][FRONT_LEFT_OF_CENTER ] += M_SQRT1_2;
205 matrix[FRONT_CENTER][FRONT_RIGHT_OF_CENTER] += M_SQRT1_2;
206 } else
207 return AVERROR_PATCHWELCOME;
208 }
209 /* mix LFE into front left/right or center */
210 if (unaccounted & AV_CH_LOW_FREQUENCY) {
211 if (out_layout & AV_CH_FRONT_CENTER) {
212 matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
213 } else if (out_layout & AV_CH_FRONT_LEFT) {
214 matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
215 matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
216 } else
217 return AVERROR_PATCHWELCOME;
218 }
219
220 /* transfer internal matrix to output matrix and calculate maximum
221 per-channel coefficient sum */
222 for (out_i = i = 0; out_i < out_channels && i < 64; i++) {
223 double sum = 0;
224 for (out_j = j = 0; out_j < in_channels && j < 64; j++) {
225 matrix_out[out_i * stride + out_j] = matrix[i][j];
226 sum += fabs(matrix[i][j]);
227 if (in_layout & (1ULL << j))
228 out_j++;
229 }
230 maxcoef = FFMAX(maxcoef, sum);
231 if (out_layout & (1ULL << i))
232 out_i++;
233 }
234
235 /* normalize */
236 if (normalize && maxcoef > 1.0) {
237 for (i = 0; i < out_channels; i++)
238 for (j = 0; j < in_channels; j++)
239 matrix_out[i * stride + j] /= maxcoef;
240 }
241
242 return 0;
243}
244
245int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
246 int stride)
247{
248 int in_channels, out_channels, i, o;
249
250 in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
251 out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
252
253 if ( in_channels < 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
254 out_channels < 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
255 av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
256 return AVERROR(EINVAL);
257 }
258
259 switch (avr->mix_coeff_type) {
260 case AV_MIX_COEFF_TYPE_Q6:
261 if (!avr->am->matrix_q6[0]) {
262 av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
263 return AVERROR(EINVAL);
264 }
265 for (o = 0; o < out_channels; o++)
266 for (i = 0; i < in_channels; i++)
267 matrix[o * stride + i] = avr->am->matrix_q6[o][i] / 64.0;
268 break;
269 case AV_MIX_COEFF_TYPE_Q15:
270 if (!avr->am->matrix_q15[0]) {
271 av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
272 return AVERROR(EINVAL);
273 }
274 for (o = 0; o < out_channels; o++)
275 for (i = 0; i < in_channels; i++)
276 matrix[o * stride + i] = avr->am->matrix_q15[o][i] / 32768.0;
277 break;
278 case AV_MIX_COEFF_TYPE_FLT:
279 if (!avr->am->matrix_flt[0]) {
280 av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
281 return AVERROR(EINVAL);
282 }
283 for (o = 0; o < out_channels; o++)
284 for (i = 0; i < in_channels; i++)
285 matrix[o * stride + i] = avr->am->matrix_flt[o][i];
286 break;
287 default:
288 av_log(avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
289 return AVERROR(EINVAL);
290 }
291 return 0;
292}
293
294int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
295 int stride)
296{
297 int in_channels, out_channels, i, o;
298
299 in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
300 out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
301
302 if ( in_channels < 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
303 out_channels < 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
304 av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
305 return AVERROR(EINVAL);
306 }
307
308 if (avr->am->matrix)
309 av_freep(avr->am->matrix);
310
311#define CONVERT_MATRIX(type, expr) \
312 avr->am->matrix_## type[0] = av_mallocz(out_channels * in_channels * \
313 sizeof(*avr->am->matrix_## type[0])); \
314 if (!avr->am->matrix_## type[0]) \
315 return AVERROR(ENOMEM); \
316 for (o = 0; o < out_channels; o++) { \
317 if (o > 0) \
318 avr->am->matrix_## type[o] = avr->am->matrix_## type[o - 1] + \
319 in_channels; \
320 for (i = 0; i < in_channels; i++) { \
321 double v = matrix[o * stride + i]; \
322 avr->am->matrix_## type[o][i] = expr; \
323 } \
324 } \
325 avr->am->matrix = (void **)avr->am->matrix_## type;
326
327 switch (avr->mix_coeff_type) {
328 case AV_MIX_COEFF_TYPE_Q6:
329 CONVERT_MATRIX(q6, av_clip_int16(lrint(64.0 * v)))
330 break;
331 case AV_MIX_COEFF_TYPE_Q15:
332 CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))
333 break;
334 case AV_MIX_COEFF_TYPE_FLT:
335 CONVERT_MATRIX(flt, v)
336 break;
337 default:
338 av_log(avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
339 return AVERROR(EINVAL);
340 }
341
342 /* TODO: detect situations where we can just swap around pointers
343 instead of doing matrix multiplications with 0.0 and 1.0 */
344
345 return 0;
346}
libavresample/avresample-test.c+340−0
@@ -0,0 +1,340 @@
1/*
2 * Copyright (c) 2002 Fabrice Bellard
3 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 *
5 * This file is part of Libav.
6 *
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdint.h>
23#include <stdio.h>
24
25#include "libavutil/avstring.h"
26#include "libavutil/lfg.h"
27#include "libavutil/libm.h"
28#include "libavutil/log.h"
29#include "libavutil/mem.h"
30#include "libavutil/opt.h"
31#include "libavutil/samplefmt.h"
32#include "avresample.h"
33
34static double dbl_rand(AVLFG *lfg)
35{
36 return 2.0 * (av_lfg_get(lfg) / (double)UINT_MAX) - 1.0;
37}
38
39#define PUT_FUNC(name, fmt, type, expr) \
40static void put_sample_ ## name(void **data, enum AVSampleFormat sample_fmt,\
41 int channels, int sample, int ch, \
42 double v_dbl) \
43{ \
44 type v = expr; \
45 type **out = (type **)data; \
46 if (av_sample_fmt_is_planar(sample_fmt)) \
47 out[ch][sample] = v; \
48 else \
49 out[0][sample * channels + ch] = v; \
50}
51
52PUT_FUNC(u8, AV_SAMPLE_FMT_U8, uint8_t, av_clip_uint8 ( lrint(v_dbl * (1 << 7)) + 128))
53PUT_FUNC(s16, AV_SAMPLE_FMT_S16, int16_t, av_clip_int16 ( lrint(v_dbl * (1 << 15))))
54PUT_FUNC(s32, AV_SAMPLE_FMT_S32, int32_t, av_clipl_int32(llrint(v_dbl * (1U << 31))))
55PUT_FUNC(flt, AV_SAMPLE_FMT_FLT, float, v_dbl)
56PUT_FUNC(dbl, AV_SAMPLE_FMT_DBL, double, v_dbl)
57
58static void put_sample(void **data, enum AVSampleFormat sample_fmt,
59 int channels, int sample, int ch, double v_dbl)
60{
61 switch (av_get_packed_sample_fmt(sample_fmt)) {
62 case AV_SAMPLE_FMT_U8:
63 put_sample_u8(data, sample_fmt, channels, sample, ch, v_dbl);
64 break;
65 case AV_SAMPLE_FMT_S16:
66 put_sample_s16(data, sample_fmt, channels, sample, ch, v_dbl);
67 break;
68 case AV_SAMPLE_FMT_S32:
69 put_sample_s32(data, sample_fmt, channels, sample, ch, v_dbl);
70 break;
71 case AV_SAMPLE_FMT_FLT:
72 put_sample_flt(data, sample_fmt, channels, sample, ch, v_dbl);
73 break;
74 case AV_SAMPLE_FMT_DBL:
75 put_sample_dbl(data, sample_fmt, channels, sample, ch, v_dbl);
76 break;
77 }
78}
79
80static void audiogen(AVLFG *rnd, void **data, enum AVSampleFormat sample_fmt,
81 int channels, int sample_rate, int nb_samples)
82{
83 int i, ch, k;
84 double v, f, a, ampa;
85 double tabf1[AVRESAMPLE_MAX_CHANNELS];
86 double tabf2[AVRESAMPLE_MAX_CHANNELS];
87 double taba[AVRESAMPLE_MAX_CHANNELS];
88
89#define PUT_SAMPLE put_sample(data, sample_fmt, channels, k, ch, v);
90
91 k = 0;
92
93 /* 1 second of single freq sinus at 1000 Hz */
94 a = 0;
95 for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
96 v = sin(a) * 0.30;
97 for (ch = 0; ch < channels; ch++)
98 PUT_SAMPLE
99 a += M_PI * 1000.0 * 2.0 / sample_rate;
100 }
101
102 /* 1 second of varing frequency between 100 and 10000 Hz */
103 a = 0;
104 for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
105 v = sin(a) * 0.30;
106 for (ch = 0; ch < channels; ch++)
107 PUT_SAMPLE
108 f = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
109 a += M_PI * f * 2.0 / sample_rate;
110 }
111
112 /* 0.5 second of low amplitude white noise */
113 for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
114 v = dbl_rand(rnd) * 0.30;
115 for (ch = 0; ch < channels; ch++)
116 PUT_SAMPLE
117 }
118
119 /* 0.5 second of high amplitude white noise */
120 for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
121 v = dbl_rand(rnd);
122 for (ch = 0; ch < channels; ch++)
123 PUT_SAMPLE
124 }
125
126 /* 1 second of unrelated ramps for each channel */
127 for (ch = 0; ch < channels; ch++) {
128 taba[ch] = 0;
129 tabf1[ch] = 100 + av_lfg_get(rnd) % 5000;
130 tabf2[ch] = 100 + av_lfg_get(rnd) % 5000;
131 }
132 for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
133 for (ch = 0; ch < channels; ch++) {
134 v = sin(taba[ch]) * 0.30;
135 PUT_SAMPLE
136 f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
137 taba[ch] += M_PI * f * 2.0 / sample_rate;
138 }
139 }
140
141 /* 2 seconds of 500 Hz with varying volume */
142 a = 0;
143 ampa = 0;
144 for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
145 for (ch = 0; ch < channels; ch++) {
146 double amp = (1.0 + sin(ampa)) * 0.15;
147 if (ch & 1)
148 amp = 0.30 - amp;
149 v = sin(a) * amp;
150 PUT_SAMPLE
151 a += M_PI * 500.0 * 2.0 / sample_rate;
152 ampa += M_PI * 2.0 / sample_rate;
153 }
154 }
155}
156
157/* formats, rates, and layouts are ordered for priority in testing.
158 e.g. 'avresample-test 4 2 2' will test all input/output combinations of
159 S16/FLTP/S16P/FLT, 48000/44100, and stereo/mono */
160
161static const enum AVSampleFormat formats[] = {
162 AV_SAMPLE_FMT_S16,
163 AV_SAMPLE_FMT_FLTP,
164 AV_SAMPLE_FMT_S16P,
165 AV_SAMPLE_FMT_FLT,
166 AV_SAMPLE_FMT_S32P,
167 AV_SAMPLE_FMT_S32,
168 AV_SAMPLE_FMT_U8P,
169 AV_SAMPLE_FMT_U8,
170 AV_SAMPLE_FMT_DBLP,
171 AV_SAMPLE_FMT_DBL,
172};
173
174static const int rates[] = {
175 48000,
176 44100,
177 16000
178};
179
180static const uint64_t layouts[] = {
181 AV_CH_LAYOUT_STEREO,
182 AV_CH_LAYOUT_MONO,
183 AV_CH_LAYOUT_5POINT1,
184 AV_CH_LAYOUT_7POINT1,
185};
186
187int main(int argc, char **argv)
188{
189 AVAudioResampleContext *s;
190 AVLFG rnd;
191 int ret = 0;
192 uint8_t *in_buf = NULL;
193 uint8_t *out_buf = NULL;
194 unsigned int in_buf_size;
195 unsigned int out_buf_size;
196 uint8_t *in_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
197 uint8_t *out_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
198 int in_linesize;
199 int out_linesize;
200 uint64_t in_ch_layout;
201 int in_channels;
202 enum AVSampleFormat in_fmt;
203 int in_rate;
204 uint64_t out_ch_layout;
205 int out_channels;
206 enum AVSampleFormat out_fmt;
207 int out_rate;
208 int num_formats, num_rates, num_layouts;
209 int i, j, k, l, m, n;
210
211 num_formats = 2;
212 num_rates = 2;
213 num_layouts = 2;
214 if (argc > 1) {
215 if (!av_strncasecmp(argv[1], "-h", 3)) {
216 av_log(NULL, AV_LOG_INFO, "Usage: avresample-test [<num formats> "
217 "[<num sample rates> [<num channel layouts>]]]\n"
218 "Default is 2 2 2\n");
219 return 0;
220 }
221 num_formats = strtol(argv[1], NULL, 0);
222 num_formats = av_clip(num_formats, 1, FF_ARRAY_ELEMS(formats));
223 }
224 if (argc > 2) {
225 num_rates = strtol(argv[2], NULL, 0);
226 num_rates = av_clip(num_rates, 1, FF_ARRAY_ELEMS(rates));
227 }
228 if (argc > 3) {
229 num_layouts = strtol(argv[3], NULL, 0);
230 num_layouts = av_clip(num_layouts, 1, FF_ARRAY_ELEMS(layouts));
231 }
232
233 av_log_set_level(AV_LOG_DEBUG);
234
235 av_lfg_init(&rnd, 0xC0FFEE);
236
237 in_buf_size = av_samples_get_buffer_size(&in_linesize, 8, 48000 * 6,
238 AV_SAMPLE_FMT_DBLP, 0);
239 out_buf_size = in_buf_size;
240
241 in_buf = av_malloc(in_buf_size);
242 if (!in_buf)
243 goto end;
244 out_buf = av_malloc(out_buf_size);
245 if (!out_buf)
246 goto end;
247
248 s = avresample_alloc_context();
249 if (!s) {
250 av_log(NULL, AV_LOG_ERROR, "Error allocating AVAudioResampleContext\n");
251 ret = 1;
252 goto end;
253 }
254
255 for (i = 0; i < num_formats; i++) {
256 in_fmt = formats[i];
257 for (k = 0; k < num_layouts; k++) {
258 in_ch_layout = layouts[k];
259 in_channels = av_get_channel_layout_nb_channels(in_ch_layout);
260 for (m = 0; m < num_rates; m++) {
261 in_rate = rates[m];
262
263 ret = av_samples_fill_arrays(in_data, &in_linesize, in_buf,
264 in_channels, in_rate * 6,
265 in_fmt, 0);
266 if (ret < 0) {
267 av_log(s, AV_LOG_ERROR, "failed in_data fill arrays\n");
268 goto end;
269 }
270 audiogen(&rnd, (void **)in_data, in_fmt, in_channels, in_rate, in_rate * 6);
271
272 for (j = 0; j < num_formats; j++) {
273 out_fmt = formats[j];
274 for (l = 0; l < num_layouts; l++) {
275 out_ch_layout = layouts[l];
276 out_channels = av_get_channel_layout_nb_channels(out_ch_layout);
277 for (n = 0; n < num_rates; n++) {
278 out_rate = rates[n];
279
280 av_log(NULL, AV_LOG_INFO, "%s to %s, %d to %d channels, %d Hz to %d Hz\n",
281 av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt),
282 in_channels, out_channels, in_rate, out_rate);
283
284 ret = av_samples_fill_arrays(out_data, &out_linesize,
285 out_buf, out_channels,
286 out_rate * 6, out_fmt, 0);
287 if (ret < 0) {
288 av_log(s, AV_LOG_ERROR, "failed out_data fill arrays\n");
289 goto end;
290 }
291
292 av_opt_set_int(s, "in_channel_layout", in_ch_layout, 0);
293 av_opt_set_int(s, "in_sample_fmt", in_fmt, 0);
294 av_opt_set_int(s, "in_sample_rate", in_rate, 0);
295 av_opt_set_int(s, "out_channel_layout", out_ch_layout, 0);
296 av_opt_set_int(s, "out_sample_fmt", out_fmt, 0);
297 av_opt_set_int(s, "out_sample_rate", out_rate, 0);
298
299 av_opt_set_int(s, "internal_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
300
301 ret = avresample_open(s);
302 if (ret < 0) {
303 av_log(s, AV_LOG_ERROR, "Error opening context\n");
304 goto end;
305 }
306
307 ret = avresample_convert(s, (void **)out_data, out_linesize, out_rate * 6,
308 (void **) in_data, in_linesize, in_rate * 6);
309 if (ret < 0) {
310 char errbuf[256];
311 av_strerror(ret, errbuf, sizeof(errbuf));
312 av_log(NULL, AV_LOG_ERROR, "%s\n", errbuf);
313 goto end;
314 }
315 av_log(NULL, AV_LOG_INFO, "Converted %d samples to %d samples\n",
316 in_rate * 6, ret);
317 if (avresample_get_delay(s) > 0)
318 av_log(NULL, AV_LOG_INFO, "%d delay samples not converted\n",
319 avresample_get_delay(s));
320 if (avresample_available(s) > 0)
321 av_log(NULL, AV_LOG_INFO, "%d samples available for output\n",
322 avresample_available(s));
323 av_log(NULL, AV_LOG_INFO, "\n");
324
325 avresample_close(s);
326 }
327 }
328 }
329 }
330 }
331 }
332
333 ret = 0;
334
335end:
336 av_freep(&in_buf);
337 av_freep(&out_buf);
338 avresample_free(&s);
339 return ret;
340}
libavresample/avresample.h+283−0
@@ -0,0 +1,283 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_AVRESAMPLE_H
22#define AVRESAMPLE_AVRESAMPLE_H
23
24/**
25 * @file
26 * external API header
27 */
28
29#include "libavutil/audioconvert.h"
30#include "libavutil/avutil.h"
31#include "libavutil/dict.h"
32#include "libavutil/log.h"
33
34#include "libavresample/version.h"
35
36#define AVRESAMPLE_MAX_CHANNELS 32
37
38typedef struct AVAudioResampleContext AVAudioResampleContext;
39
40/** Mixing Coefficient Types */
41enum AVMixCoeffType {
42 AV_MIX_COEFF_TYPE_Q6, /** 16-bit 10.6 fixed-point */
43 AV_MIX_COEFF_TYPE_Q15, /** 32-bit 17.15 fixed-point */
44 AV_MIX_COEFF_TYPE_FLT, /** floating-point */
45 AV_MIX_COEFF_TYPE_NB, /** Number of coeff types. Not part of ABI */
46};
47
48/**
49 * Return the LIBAVRESAMPLE_VERSION_INT constant.
50 */
51unsigned avresample_version(void);
52
53/**
54 * Return the libavresample build-time configuration.
55 * @return configure string
56 */
57const char *avresample_configuration(void);
58
59/**
60 * Return the libavresample license.
61 */
62const char *avresample_license(void);
63
64/**
65 * Get the AVClass for AVAudioResampleContext.
66 *
67 * Can be used in combination with AV_OPT_SEARCH_FAKE_OBJ for examining options
68 * without allocating a context.
69 *
70 * @see av_opt_find().
71 *
72 * @return AVClass for AVAudioResampleContext
73 */
74const AVClass *avresample_get_class(void);
75
76/**
77 * Allocate AVAudioResampleContext and set options.
78 *
79 * @return allocated audio resample context, or NULL on failure
80 */
81AVAudioResampleContext *avresample_alloc_context(void);
82
83/**
84 * Initialize AVAudioResampleContext.
85 *
86 * @param avr audio resample context
87 * @return 0 on success, negative AVERROR code on failure
88 */
89int avresample_open(AVAudioResampleContext *avr);
90
91/**
92 * Close AVAudioResampleContext.
93 *
94 * This closes the context, but it does not change the parameters. The context
95 * can be reopened with avresample_open(). It does, however, clear the output
96 * FIFO and any remaining leftover samples in the resampling delay buffer. If
97 * there was a custom matrix being used, that is also cleared.
98 *
99 * @see avresample_convert()
100 * @see avresample_set_matrix()
101 *
102 * @param avr audio resample context
103 */
104void avresample_close(AVAudioResampleContext *avr);
105
106/**
107 * Free AVAudioResampleContext and associated AVOption values.
108 *
109 * This also calls avresample_close() before freeing.
110 *
111 * @param avr audio resample context
112 */
113void avresample_free(AVAudioResampleContext **avr);
114
115/**
116 * Generate a channel mixing matrix.
117 *
118 * This function is the one used internally by libavresample for building the
119 * default mixing matrix. It is made public just as a utility function for
120 * building custom matrices.
121 *
122 * @param in_layout input channel layout
123 * @param out_layout output channel layout
124 * @param center_mix_level mix level for the center channel
125 * @param surround_mix_level mix level for the surround channel(s)
126 * @param lfe_mix_level mix level for the low-frequency effects channel
127 * @param normalize if 1, coefficients will be normalized to prevent
128 * overflow. if 0, coefficients will not be
129 * normalized.
130 * @param[out] matrix mixing coefficients; matrix[i + stride * o] is
131 * the weight of input channel i in output channel o.
132 * @param stride distance between adjacent input channels in the
133 * matrix array
134 * @return 0 on success, negative AVERROR code on failure
135 */
136int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
137 double center_mix_level, double surround_mix_level,
138 double lfe_mix_level, int normalize, double *matrix,
139 int stride);
140
141/**
142 * Get the current channel mixing matrix.
143 *
144 * @param avr audio resample context
145 * @param matrix mixing coefficients; matrix[i + stride * o] is the weight of
146 * input channel i in output channel o.
147 * @param stride distance between adjacent input channels in the matrix array
148 * @return 0 on success, negative AVERROR code on failure
149 */
150int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
151 int stride);
152
153/**
154 * Set channel mixing matrix.
155 *
156 * Allows for setting a custom mixing matrix, overriding the default matrix
157 * generated internally during avresample_open(). This function can be called
158 * anytime on an allocated context, either before or after calling
159 * avresample_open(). avresample_convert() always uses the current matrix.
160 * Calling avresample_close() on the context will clear the current matrix.
161 *
162 * @see avresample_close()
163 *
164 * @param avr audio resample context
165 * @param matrix mixing coefficients; matrix[i + stride * o] is the weight of
166 * input channel i in output channel o.
167 * @param stride distance between adjacent input channels in the matrix array
168 * @return 0 on success, negative AVERROR code on failure
169 */
170int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
171 int stride);
172
173/**
174 * Set compensation for resampling.
175 *
176 * This can be called anytime after avresample_open(). If resampling was not
177 * being done previously, the AVAudioResampleContext is closed and reopened
178 * with resampling enabled. In this case, any samples remaining in the output
179 * FIFO and the current channel mixing matrix will be restored after reopening
180 * the context.
181 *
182 * @param avr audio resample context
183 * @param sample_delta compensation delta, in samples
184 * @param compensation_distance compensation distance, in samples
185 * @return 0 on success, negative AVERROR code on failure
186 */
187int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta,
188 int compensation_distance);
189
190/**
191 * Convert input samples and write them to the output FIFO.
192 *
193 * The output data can be NULL or have fewer allocated samples than required.
194 * In this case, any remaining samples not written to the output will be added
195 * to an internal FIFO buffer, to be returned at the next call to this function
196 * or to avresample_read().
197 *
198 * If converting sample rate, there may be data remaining in the internal
199 * resampling delay buffer. avresample_get_delay() tells the number of remaining
200 * samples. To get this data as output, call avresample_convert() with NULL
201 * input.
202 *
203 * At the end of the conversion process, there may be data remaining in the
204 * internal FIFO buffer. avresample_available() tells the number of remaining
205 * samples. To get this data as output, either call avresample_convert() with
206 * NULL input or call avresample_read().
207 *
208 * @see avresample_available()
209 * @see avresample_read()
210 * @see avresample_get_delay()
211 *
212 * @param avr audio resample context
213 * @param output output data pointers
214 * @param out_plane_size output plane size, in bytes.
215 * This can be 0 if unknown, but that will lead to
216 * optimized functions not being used directly on the
217 * output, which could slow down some conversions.
218 * @param out_samples maximum number of samples that the output buffer can hold
219 * @param input input data pointers
220 * @param in_plane_size input plane size, in bytes
221 * This can be 0 if unknown, but that will lead to
222 * optimized functions not being used directly on the
223 * input, which could slow down some conversions.
224 * @param in_samples number of input samples to convert
225 * @return number of samples written to the output buffer,
226 * not including converted samples added to the internal
227 * output FIFO
228 */
229int avresample_convert(AVAudioResampleContext *avr, void **output,
230 int out_plane_size, int out_samples, void **input,
231 int in_plane_size, int in_samples);
232
233/**
234 * Return the number of samples currently in the resampling delay buffer.
235 *
236 * When resampling, there may be a delay between the input and output. Any
237 * unconverted samples in each call are stored internally in a delay buffer.
238 * This function allows the user to determine the current number of samples in
239 * the delay buffer, which can be useful for synchronization.
240 *
241 * @see avresample_convert()
242 *
243 * @param avr audio resample context
244 * @return number of samples currently in the resampling delay buffer
245 */
246int avresample_get_delay(AVAudioResampleContext *avr);
247
248/**
249 * Return the number of available samples in the output FIFO.
250 *
251 * During conversion, if the user does not specify an output buffer or
252 * specifies an output buffer that is smaller than what is needed, remaining
253 * samples that are not written to the output are stored to an internal FIFO
254 * buffer. The samples in the FIFO can be read with avresample_read() or
255 * avresample_convert().
256 *
257 * @see avresample_read()
258 * @see avresample_convert()
259 *
260 * @param avr audio resample context
261 * @return number of samples available for reading
262 */
263int avresample_available(AVAudioResampleContext *avr);
264
265/**
266 * Read samples from the output FIFO.
267 *
268 * During conversion, if the user does not specify an output buffer or
269 * specifies an output buffer that is smaller than what is needed, remaining
270 * samples that are not written to the output are stored to an internal FIFO
271 * buffer. This function can be used to read samples from that internal FIFO.
272 *
273 * @see avresample_available()
274 * @see avresample_convert()
275 *
276 * @param avr audio resample context
277 * @param output output data pointers
278 * @param nb_samples number of samples to read from the FIFO
279 * @return the number of samples written to output
280 */
281int avresample_read(AVAudioResampleContext *avr, void **output, int nb_samples);
282
283#endif /* AVRESAMPLE_AVRESAMPLE_H */
libavresample/internal.h+75−0
@@ -0,0 +1,75 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_INTERNAL_H
22#define AVRESAMPLE_INTERNAL_H
23
24#include "libavutil/audio_fifo.h"
25#include "libavutil/log.h"
26#include "libavutil/opt.h"
27#include "libavutil/samplefmt.h"
28#include "avresample.h"
29#include "audio_convert.h"
30#include "audio_data.h"
31#include "audio_mix.h"
32#include "resample.h"
33
34struct AVAudioResampleContext {
35 const AVClass *av_class; /**< AVClass for logging and AVOptions */
36
37 uint64_t in_channel_layout; /**< input channel layout */
38 enum AVSampleFormat in_sample_fmt; /**< input sample format */
39 int in_sample_rate; /**< input sample rate */
40 uint64_t out_channel_layout; /**< output channel layout */
41 enum AVSampleFormat out_sample_fmt; /**< output sample format */
42 int out_sample_rate; /**< output sample rate */
43 enum AVSampleFormat internal_sample_fmt; /**< internal sample format */
44 enum AVMixCoeffType mix_coeff_type; /**< mixing coefficient type */
45 double center_mix_level; /**< center mix level */
46 double surround_mix_level; /**< surround mix level */
47 double lfe_mix_level; /**< lfe mix level */
48 int force_resampling; /**< force resampling */
49 int filter_size; /**< length of each FIR filter in the resampling filterbank relative to the cutoff frequency */
50 int phase_shift; /**< log2 of the number of entries in the resampling polyphase filterbank */
51 int linear_interp; /**< if 1 then the resampling FIR filter will be linearly interpolated */
52 double cutoff; /**< resampling cutoff frequency. 1.0 corresponds to half the output sample rate */
53
54 int in_channels; /**< number of input channels */
55 int out_channels; /**< number of output channels */
56 int resample_channels; /**< number of channels used for resampling */
57 int downmix_needed; /**< downmixing is needed */
58 int upmix_needed; /**< upmixing is needed */
59 int mixing_needed; /**< either upmixing or downmixing is needed */
60 int resample_needed; /**< resampling is needed */
61 int in_convert_needed; /**< input sample format conversion is needed */
62 int out_convert_needed; /**< output sample format conversion is needed */
63
64 AudioData *in_buffer; /**< buffer for converted input */
65 AudioData *resample_out_buffer; /**< buffer for output from resampler */
66 AudioData *out_buffer; /**< buffer for converted output */
67 AVAudioFifo *out_fifo; /**< FIFO for output samples */
68
69 AudioConvert *ac_in; /**< input sample format conversion context */
70 AudioConvert *ac_out; /**< output sample format conversion context */
71 ResampleContext *resample; /**< resampling context */
72 AudioMix *am; /**< channel mixing context */
73};
74
75#endif /* AVRESAMPLE_INTERNAL_H */
libavresample/libavresample.v+4−0
@@ -0,0 +1,4 @@
1LIBAVRESAMPLE_$MAJOR {
2 global: av*;
3 local: *;
4};
libavresample/options.c+89−0
@@ -0,0 +1,89 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "libavutil/mathematics.h"
22#include "libavutil/opt.h"
23#include "avresample.h"
24#include "internal.h"
25#include "audio_mix.h"
26
27/**
28 * @file
29 * Options definition for AVAudioResampleContext.
30 */
31
32#define OFFSET(x) offsetof(AVAudioResampleContext, x)
33#define PARAM AV_OPT_FLAG_AUDIO_PARAM
34
35static const AVOption options[] = {
36 { "in_channel_layout", "Input Channel Layout", OFFSET(in_channel_layout), AV_OPT_TYPE_INT64, { 0 }, INT64_MIN, INT64_MAX, PARAM },
37 { "in_sample_fmt", "Input Sample Format", OFFSET(in_sample_fmt), AV_OPT_TYPE_INT, { AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM },
38 { "in_sample_rate", "Input Sample Rate", OFFSET(in_sample_rate), AV_OPT_TYPE_INT, { 48000 }, 1, INT_MAX, PARAM },
39 { "out_channel_layout", "Output Channel Layout", OFFSET(out_channel_layout), AV_OPT_TYPE_INT64, { 0 }, INT64_MIN, INT64_MAX, PARAM },
40 { "out_sample_fmt", "Output Sample Format", OFFSET(out_sample_fmt), AV_OPT_TYPE_INT, { AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM },
41 { "out_sample_rate", "Output Sample Rate", OFFSET(out_sample_rate), AV_OPT_TYPE_INT, { 48000 }, 1, INT_MAX, PARAM },
42 { "internal_sample_fmt", "Internal Sample Format", OFFSET(internal_sample_fmt), AV_OPT_TYPE_INT, { AV_SAMPLE_FMT_FLTP }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, PARAM },
43 { "mix_coeff_type", "Mixing Coefficient Type", OFFSET(mix_coeff_type), AV_OPT_TYPE_INT, { AV_MIX_COEFF_TYPE_FLT }, AV_MIX_COEFF_TYPE_Q6, AV_MIX_COEFF_TYPE_NB-1, PARAM, "mix_coeff_type" },
44 { "q6", "16-bit 10.6 Fixed-Point", 0, AV_OPT_TYPE_CONST, { AV_MIX_COEFF_TYPE_Q6 }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" },
45 { "q15", "32-bit 17.15 Fixed-Point", 0, AV_OPT_TYPE_CONST, { AV_MIX_COEFF_TYPE_Q15 }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" },
46 { "flt", "Floating-Point", 0, AV_OPT_TYPE_CONST, { AV_MIX_COEFF_TYPE_FLT }, INT_MIN, INT_MAX, PARAM, "mix_coeff_type" },
47 { "center_mix_level", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_DOUBLE, { M_SQRT1_2 }, -32.0, 32.0, PARAM },
48 { "surround_mix_level", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_DOUBLE, { M_SQRT1_2 }, -32.0, 32.0, PARAM },
49 { "lfe_mix_level", "LFE Mix Level", OFFSET(lfe_mix_level), AV_OPT_TYPE_DOUBLE, { 0.0 }, -32.0, 32.0, PARAM },
50 { "force_resampling", "Force Resampling", OFFSET(force_resampling), AV_OPT_TYPE_INT, { 0 }, 0, 1, PARAM },
51 { "filter_size", "Resampling Filter Size", OFFSET(filter_size), AV_OPT_TYPE_INT, { 16 }, 0, 32, /* ??? */ PARAM },
52 { "phase_shift", "Resampling Phase Shift", OFFSET(phase_shift), AV_OPT_TYPE_INT, { 10 }, 0, 30, /* ??? */ PARAM },
53 { "linear_interp", "Use Linear Interpolation", OFFSET(linear_interp), AV_OPT_TYPE_INT, { 0 }, 0, 1, PARAM },
54 { "cutoff", "Cutoff Frequency Ratio", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, { 0.8 }, 0.0, 1.0, PARAM },
55 { NULL },
56};
57
58static const AVClass av_resample_context_class = {
59 .class_name = "AVAudioResampleContext",
60 .item_name = av_default_item_name,
61 .option = options,
62 .version = LIBAVUTIL_VERSION_INT,
63};
64
65AVAudioResampleContext *avresample_alloc_context(void)
66{
67 AVAudioResampleContext *avr;
68
69 avr = av_mallocz(sizeof(*avr));
70 if (!avr)
71 return NULL;
72
73 avr->av_class = &av_resample_context_class;
74 av_opt_set_defaults(avr);
75
76 avr->am = av_mallocz(sizeof(*avr->am));
77 if (!avr->am) {
78 av_free(avr);
79 return NULL;
80 }
81 avr->am->avr = avr;
82
83 return avr;
84}
85
86const AVClass *avresample_get_class(void)
87{
88 return &av_resample_context_class;
89}
libavresample/resample.c+480−0
@@ -0,0 +1,480 @@
1/*
2 * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 *
5 * This file is part of Libav.
6 *
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavutil/libm.h"
23#include "libavutil/log.h"
24#include "internal.h"
25#include "audio_data.h"
26
27#ifdef CONFIG_RESAMPLE_FLT
28/* float template */
29#define FILTER_SHIFT 0
30#define FELEM float
31#define FELEM2 float
32#define FELEML float
33#define WINDOW_TYPE 24
34#elifdef CONFIG_RESAMPLE_S32
35/* s32 template */
36#define FILTER_SHIFT 30
37#define FELEM int32_t
38#define FELEM2 int64_t
39#define FELEML int64_t
40#define FELEM_MAX INT32_MAX
41#define FELEM_MIN INT32_MIN
42#define WINDOW_TYPE 12
43#else
44/* s16 template */
45#define FILTER_SHIFT 15
46#define FELEM int16_t
47#define FELEM2 int32_t
48#define FELEML int64_t
49#define FELEM_MAX INT16_MAX
50#define FELEM_MIN INT16_MIN
51#define WINDOW_TYPE 9
52#endif
53
54struct ResampleContext {
55 AVAudioResampleContext *avr;
56 AudioData *buffer;
57 FELEM *filter_bank;
58 int filter_length;
59 int ideal_dst_incr;
60 int dst_incr;
61 int index;
62 int frac;
63 int src_incr;
64 int compensation_distance;
65 int phase_shift;
66 int phase_mask;
67 int linear;
68 double factor;
69};
70
71/**
72 * 0th order modified bessel function of the first kind.
73 */
74static double bessel(double x)
75{
76 double v = 1;
77 double lastv = 0;
78 double t = 1;
79 int i;
80
81 x = x * x / 4;
82 for (i = 1; v != lastv; i++) {
83 lastv = v;
84 t *= x / (i * i);
85 v += t;
86 }
87 return v;
88}
89
90/**
91 * Build a polyphase filterbank.
92 *
93 * @param[out] filter filter coefficients
94 * @param factor resampling factor
95 * @param tap_count tap count
96 * @param phase_count phase count
97 * @param scale wanted sum of coefficients for each filter
98 * @param type 0->cubic
99 * 1->blackman nuttall windowed sinc
100 * 2..16->kaiser windowed sinc beta=2..16
101 * @return 0 on success, negative AVERROR code on failure
102 */
103static int build_filter(FELEM *filter, double factor, int tap_count,
104 int phase_count, int scale, int type)
105{
106 int ph, i;
107 double x, y, w;
108 double *tab;
109 const int center = (tap_count - 1) / 2;
110
111 tab = av_malloc(tap_count * sizeof(*tab));
112 if (!tab)
113 return AVERROR(ENOMEM);
114
115 /* if upsampling, only need to interpolate, no filter */
116 if (factor > 1.0)
117 factor = 1.0;
118
119 for (ph = 0; ph < phase_count; ph++) {
120 double norm = 0;
121 for (i = 0; i < tap_count; i++) {
122 x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
123 if (x == 0) y = 1.0;
124 else y = sin(x) / x;
125 switch (type) {
126 case 0: {
127 const float d = -0.5; //first order derivative = -0.5
128 x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
129 if (x < 1.0) y = 1 - 3 * x*x + 2 * x*x*x + d * ( -x*x + x*x*x);
130 else y = d * (-4 + 8 * x - 5 * x*x + x*x*x);
131 break;
132 }
133 case 1:
134 w = 2.0 * x / (factor * tap_count) + M_PI;
135 y *= 0.3635819 - 0.4891775 * cos( w) +
136 0.1365995 * cos(2 * w) -
137 0.0106411 * cos(3 * w);
138 break;
139 default:
140 w = 2.0 * x / (factor * tap_count * M_PI);
141 y *= bessel(type * sqrt(FFMAX(1 - w * w, 0)));
142 break;
143 }
144
145 tab[i] = y;
146 norm += y;
147 }
148
149 /* normalize so that an uniform color remains the same */
150 for (i = 0; i < tap_count; i++) {
151#ifdef CONFIG_RESAMPLE_FLT
152 filter[ph * tap_count + i] = tab[i] / norm;
153#else
154 filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm),
155 FELEM_MIN, FELEM_MAX);
156#endif
157 }
158 }
159
160 av_free(tab);
161 return 0;
162}
163
164ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr)
165{
166 ResampleContext *c;
167 int out_rate = avr->out_sample_rate;
168 int in_rate = avr->in_sample_rate;
169 double factor = FFMIN(out_rate * avr->cutoff / in_rate, 1.0);
170 int phase_count = 1 << avr->phase_shift;
171
172 /* TODO: add support for s32 and float internal formats */
173 if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P) {
174 av_log(avr, AV_LOG_ERROR, "Unsupported internal format for "
175 "resampling: %s\n",
176 av_get_sample_fmt_name(avr->internal_sample_fmt));
177 return NULL;
178 }
179 c = av_mallocz(sizeof(*c));
180 if (!c)
181 return NULL;
182
183 c->avr = avr;
184 c->phase_shift = avr->phase_shift;
185 c->phase_mask = phase_count - 1;
186 c->linear = avr->linear_interp;
187 c->factor = factor;
188 c->filter_length = FFMAX((int)ceil(avr->filter_size / factor), 1);
189
190 c->filter_bank = av_mallocz(c->filter_length * (phase_count + 1) * sizeof(FELEM));
191 if (!c->filter_bank)
192 goto error;
193
194 if (build_filter(c->filter_bank, factor, c->filter_length, phase_count,
195 1 << FILTER_SHIFT, WINDOW_TYPE) < 0)
196 goto error;
197
198 memcpy(&c->filter_bank[c->filter_length * phase_count + 1],
199 c->filter_bank, (c->filter_length - 1) * sizeof(FELEM));
200 c->filter_bank[c->filter_length * phase_count] = c->filter_bank[c->filter_length - 1];
201
202 c->compensation_distance = 0;
203 if (!av_reduce(&c->src_incr, &c->dst_incr, out_rate,
204 in_rate * (int64_t)phase_count, INT32_MAX / 2))
205 goto error;
206 c->ideal_dst_incr = c->dst_incr;
207
208 c->index = -phase_count * ((c->filter_length - 1) / 2);
209 c->frac = 0;
210
211 /* allocate internal buffer */
212 c->buffer = ff_audio_data_alloc(avr->resample_channels, 0,
213 avr->internal_sample_fmt,
214 "resample buffer");
215 if (!c->buffer)
216 goto error;
217
218 av_log(avr, AV_LOG_DEBUG, "resample: %s from %d Hz to %d Hz\n",
219 av_get_sample_fmt_name(avr->internal_sample_fmt),
220 avr->in_sample_rate, avr->out_sample_rate);
221
222 return c;
223
224error:
225 ff_audio_data_free(&c->buffer);
226 av_free(c->filter_bank);
227 av_free(c);
228 return NULL;
229}
230
231void ff_audio_resample_free(ResampleContext **c)
232{
233 if (!*c)
234 return;
235 ff_audio_data_free(&(*c)->buffer);
236 av_free((*c)->filter_bank);
237 av_freep(c);
238}
239
240int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta,
241 int compensation_distance)
242{
243 ResampleContext *c;
244 AudioData *fifo_buf = NULL;
245 int ret = 0;
246
247 if (compensation_distance < 0)
248 return AVERROR(EINVAL);
249 if (!compensation_distance && sample_delta)
250 return AVERROR(EINVAL);
251
252 /* if resampling was not enabled previously, re-initialize the
253 AVAudioResampleContext and force resampling */
254 if (!avr->resample_needed) {
255 int fifo_samples;
256 double matrix[AVRESAMPLE_MAX_CHANNELS * AVRESAMPLE_MAX_CHANNELS] = { 0 };
257
258 /* buffer any remaining samples in the output FIFO before closing */
259 fifo_samples = av_audio_fifo_size(avr->out_fifo);
260 if (fifo_samples > 0) {
261 fifo_buf = ff_audio_data_alloc(avr->out_channels, fifo_samples,
262 avr->out_sample_fmt, NULL);
263 if (!fifo_buf)
264 return AVERROR(EINVAL);
265 ret = ff_audio_data_read_from_fifo(avr->out_fifo, fifo_buf,
266 fifo_samples);
267 if (ret < 0)
268 goto reinit_fail;
269 }
270 /* save the channel mixing matrix */
271 ret = avresample_get_matrix(avr, matrix, AVRESAMPLE_MAX_CHANNELS);
272 if (ret < 0)
273 goto reinit_fail;
274
275 /* close the AVAudioResampleContext */
276 avresample_close(avr);
277
278 avr->force_resampling = 1;
279
280 /* restore the channel mixing matrix */
281 ret = avresample_set_matrix(avr, matrix, AVRESAMPLE_MAX_CHANNELS);
282 if (ret < 0)
283 goto reinit_fail;
284
285 /* re-open the AVAudioResampleContext */
286 ret = avresample_open(avr);
287 if (ret < 0)
288 goto reinit_fail;
289
290 /* restore buffered samples to the output FIFO */
291 if (fifo_samples > 0) {
292 ret = ff_audio_data_add_to_fifo(avr->out_fifo, fifo_buf, 0,
293 fifo_samples);
294 if (ret < 0)
295 goto reinit_fail;
296 ff_audio_data_free(&fifo_buf);
297 }
298 }
299 c = avr->resample;
300 c->compensation_distance = compensation_distance;
301 if (compensation_distance) {
302 c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr *
303 (int64_t)sample_delta / compensation_distance;
304 } else {
305 c->dst_incr = c->ideal_dst_incr;
306 }
307 return 0;
308
309reinit_fail:
310 ff_audio_data_free(&fifo_buf);
311 return ret;
312}
313
314static int resample(ResampleContext *c, int16_t *dst, const int16_t *src,
315 int *consumed, int src_size, int dst_size, int update_ctx)
316{
317 int dst_index, i;
318 int index = c->index;
319 int frac = c->frac;
320 int dst_incr_frac = c->dst_incr % c->src_incr;
321 int dst_incr = c->dst_incr / c->src_incr;
322 int compensation_distance = c->compensation_distance;
323
324 if (!dst != !src)
325 return AVERROR(EINVAL);
326
327 if (compensation_distance == 0 && c->filter_length == 1 &&
328 c->phase_shift == 0) {
329 int64_t index2 = ((int64_t)index) << 32;
330 int64_t incr = (1LL << 32) * c->dst_incr / c->src_incr;
331 dst_size = FFMIN(dst_size,
332 (src_size-1-index) * (int64_t)c->src_incr /
333 c->dst_incr);
334
335 if (dst) {
336 for(dst_index = 0; dst_index < dst_size; dst_index++) {
337 dst[dst_index] = src[index2 >> 32];
338 index2 += incr;
339 }
340 } else {
341 dst_index = dst_size;
342 }
343 index += dst_index * dst_incr;
344 index += (frac + dst_index * (int64_t)dst_incr_frac) / c->src_incr;
345 frac = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr;
346 } else {
347 for (dst_index = 0; dst_index < dst_size; dst_index++) {
348 FELEM *filter = c->filter_bank +
349 c->filter_length * (index & c->phase_mask);
350 int sample_index = index >> c->phase_shift;
351
352 if (!dst && (sample_index + c->filter_length > src_size ||
353 -sample_index >= src_size))
354 break;
355
356 if (dst) {
357 FELEM2 val = 0;
358
359 if (sample_index < 0) {
360 for (i = 0; i < c->filter_length; i++)
361 val += src[FFABS(sample_index + i) % src_size] *
362 (FELEM2)filter[i];
363 } else if (sample_index + c->filter_length > src_size) {
364 break;
365 } else if (c->linear) {
366 FELEM2 v2 = 0;
367 for (i = 0; i < c->filter_length; i++) {
368 val += src[abs(sample_index + i)] * (FELEM2)filter[i];
369 v2 += src[abs(sample_index + i)] * (FELEM2)filter[i + c->filter_length];
370 }
371 val += (v2 - val) * (FELEML)frac / c->src_incr;
372 } else {
373 for (i = 0; i < c->filter_length; i++)
374 val += src[sample_index + i] * (FELEM2)filter[i];
375 }
376
377#ifdef CONFIG_RESAMPLE_FLT
378 dst[dst_index] = av_clip_int16(lrintf(val));
379#else
380 val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;
381 dst[dst_index] = av_clip_int16(val);
382#endif
383 }
384
385 frac += dst_incr_frac;
386 index += dst_incr;
387 if (frac >= c->src_incr) {
388 frac -= c->src_incr;
389 index++;
390 }
391 if (dst_index + 1 == compensation_distance) {
392 compensation_distance = 0;
393 dst_incr_frac = c->ideal_dst_incr % c->src_incr;
394 dst_incr = c->ideal_dst_incr / c->src_incr;
395 }
396 }
397 }
398 if (consumed)
399 *consumed = FFMAX(index, 0) >> c->phase_shift;
400
401 if (update_ctx) {
402 if (index >= 0)
403 index &= c->phase_mask;
404
405 if (compensation_distance) {
406 compensation_distance -= dst_index;
407 if (compensation_distance <= 0)
408 return AVERROR_BUG;
409 }
410 c->frac = frac;
411 c->index = index;
412 c->dst_incr = dst_incr_frac + c->src_incr*dst_incr;
413 c->compensation_distance = compensation_distance;
414 }
415
416 return dst_index;
417}
418
419int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src,
420 int *consumed)
421{
422 int ch, in_samples, in_leftover, out_samples = 0;
423 int ret = AVERROR(EINVAL);
424
425 in_samples = src ? src->nb_samples : 0;
426 in_leftover = c->buffer->nb_samples;
427
428 /* add input samples to the internal buffer */
429 if (src) {
430 ret = ff_audio_data_combine(c->buffer, in_leftover, src, 0, in_samples);
431 if (ret < 0)
432 return ret;
433 } else if (!in_leftover) {
434 /* no remaining samples to flush */
435 return 0;
436 } else {
437 /* TODO: pad buffer to flush completely */
438 }
439
440 /* calculate output size and reallocate output buffer if needed */
441 /* TODO: try to calculate this without the dummy resample() run */
442 if (!dst->read_only && dst->allow_realloc) {
443 out_samples = resample(c, NULL, NULL, NULL, c->buffer->nb_samples,
444 INT_MAX, 0);
445 ret = ff_audio_data_realloc(dst, out_samples);
446 if (ret < 0) {
447 av_log(c->avr, AV_LOG_ERROR, "error reallocating output\n");
448 return ret;
449 }
450 }
451
452 /* resample each channel plane */
453 for (ch = 0; ch < c->buffer->channels; ch++) {
454 out_samples = resample(c, (int16_t *)dst->data[ch],
455 (const int16_t *)c->buffer->data[ch], consumed,
456 c->buffer->nb_samples, dst->allocated_samples,
457 ch + 1 == c->buffer->channels);
458 }
459 if (out_samples < 0) {
460 av_log(c->avr, AV_LOG_ERROR, "error during resampling\n");
461 return out_samples;
462 }
463
464 /* drain consumed samples from the internal buffer */
465 ff_audio_data_drain(c->buffer, *consumed);
466
467 av_dlog(c->avr, "resampled %d in + %d leftover to %d out + %d leftover\n",
468 in_samples, in_leftover, out_samples, c->buffer->nb_samples);
469
470 dst->nb_samples = out_samples;
471 return 0;
472}
473
474int avresample_get_delay(AVAudioResampleContext *avr)
475{
476 if (!avr->resample_needed || !avr->resample)
477 return 0;
478
479 return avr->resample->buffer->nb_samples;
480}
libavresample/resample.h+70−0
@@ -0,0 +1,70 @@
1/*
2 * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVRESAMPLE_RESAMPLE_H
22#define AVRESAMPLE_RESAMPLE_H
23
24#include "avresample.h"
25#include "audio_data.h"
26
27typedef struct ResampleContext ResampleContext;
28
29/**
30 * Allocate and initialize a ResampleContext.
31 *
32 * The parameters in the AVAudioResampleContext are used to initialize the
33 * ResampleContext.
34 *
35 * @param avr AVAudioResampleContext
36 * @return newly-allocated ResampleContext
37 */
38ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr);
39
40/**
41 * Free a ResampleContext.
42 *
43 * @param c ResampleContext
44 */
45void ff_audio_resample_free(ResampleContext **c);
46
47/**
48 * Resample audio data.
49 *
50 * Changes the sample rate.
51 *
52 * @par
53 * All samples in the source data may not be consumed depending on the
54 * resampling parameters and the size of the output buffer. The unconsumed
55 * samples are automatically added to the start of the source in the next call.
56 * If the destination data can be reallocated, that may be done in this function
57 * in order to fit all available output. If it cannot be reallocated, fewer
58 * input samples will be consumed in order to have the output fit in the
59 * destination data buffers.
60 *
61 * @param c ResampleContext
62 * @param dst destination audio data
63 * @param src source audio data
64 * @param consumed number of samples consumed from the source
65 * @return number of samples written to the destination
66 */
67int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src,
68 int *consumed);
69
70#endif /* AVRESAMPLE_RESAMPLE_H */
libavresample/utils.c+405−0
@@ -0,0 +1,405 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "libavutil/dict.h"
22// #include "libavutil/error.h"
23#include "libavutil/log.h"
24#include "libavutil/mem.h"
25#include "libavutil/opt.h"
26
27#include "avresample.h"
28#include "audio_data.h"
29#include "internal.h"
30
31int avresample_open(AVAudioResampleContext *avr)
32{
33 int ret;
34
35 /* set channel mixing parameters */
36 avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
37 if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
38 av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
39 avr->in_channel_layout);
40 return AVERROR(EINVAL);
41 }
42 avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
43 if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
44 av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
45 avr->out_channel_layout);
46 return AVERROR(EINVAL);
47 }
48 avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels);
49 avr->downmix_needed = avr->in_channels > avr->out_channels;
50 avr->upmix_needed = avr->out_channels > avr->in_channels ||
51 avr->am->matrix ||
52 (avr->out_channels == avr->in_channels &&
53 avr->in_channel_layout != avr->out_channel_layout);
54 avr->mixing_needed = avr->downmix_needed || avr->upmix_needed;
55
56 /* set resampling parameters */
57 avr->resample_needed = avr->in_sample_rate != avr->out_sample_rate ||
58 avr->force_resampling;
59
60 /* set sample format conversion parameters */
61 /* override user-requested internal format to avoid unexpected failures
62 TODO: support more internal formats */
63 if (avr->resample_needed && avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P) {
64 av_log(avr, AV_LOG_WARNING, "Using s16p as internal sample format\n");
65 avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P;
66 } else if (avr->mixing_needed &&
67 avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P &&
68 avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) {
69 av_log(avr, AV_LOG_WARNING, "Using fltp as internal sample format\n");
70 avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
71 }
72 if (avr->in_channels == 1)
73 avr->in_sample_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
74 if (avr->out_channels == 1)
75 avr->out_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
76 avr->in_convert_needed = (avr->resample_needed || avr->mixing_needed) &&
77 avr->in_sample_fmt != avr->internal_sample_fmt;
78 if (avr->resample_needed || avr->mixing_needed)
79 avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt;
80 else
81 avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt;
82
83 /* allocate buffers */
84 if (avr->mixing_needed || avr->in_convert_needed) {
85 avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels),
86 0, avr->internal_sample_fmt,
87 "in_buffer");
88 if (!avr->in_buffer) {
89 ret = AVERROR(EINVAL);
90 goto error;
91 }
92 }
93 if (avr->resample_needed) {
94 avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels,
95 0, avr->internal_sample_fmt,
96 "resample_out_buffer");
97 if (!avr->resample_out_buffer) {
98 ret = AVERROR(EINVAL);
99 goto error;
100 }
101 }
102 if (avr->out_convert_needed) {
103 avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0,
104 avr->out_sample_fmt, "out_buffer");
105 if (!avr->out_buffer) {
106 ret = AVERROR(EINVAL);
107 goto error;
108 }
109 }
110 avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels,
111 1024);
112 if (!avr->out_fifo) {
113 ret = AVERROR(ENOMEM);
114 goto error;
115 }
116
117 /* setup contexts */
118 if (avr->in_convert_needed) {
119 avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt,
120 avr->in_sample_fmt, avr->in_channels);
121 if (!avr->ac_in) {
122 ret = AVERROR(ENOMEM);
123 goto error;
124 }
125 }
126 if (avr->out_convert_needed) {
127 enum AVSampleFormat src_fmt;
128 if (avr->in_convert_needed)
129 src_fmt = avr->internal_sample_fmt;
130 else
131 src_fmt = avr->in_sample_fmt;
132 avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
133 avr->out_channels);
134 if (!avr->ac_out) {
135 ret = AVERROR(ENOMEM);
136 goto error;
137 }
138 }
139 if (avr->resample_needed) {
140 avr->resample = ff_audio_resample_init(avr);
141 if (!avr->resample) {
142 ret = AVERROR(ENOMEM);
143 goto error;
144 }
145 }
146 if (avr->mixing_needed) {
147 ret = ff_audio_mix_init(avr);
148 if (ret < 0)
149 goto error;
150 }
151
152 return 0;
153
154error:
155 avresample_close(avr);
156 return ret;
157}
158
159void avresample_close(AVAudioResampleContext *avr)
160{
161 ff_audio_data_free(&avr->in_buffer);
162 ff_audio_data_free(&avr->resample_out_buffer);
163 ff_audio_data_free(&avr->out_buffer);
164 av_audio_fifo_free(avr->out_fifo);
165 avr->out_fifo = NULL;
166 av_freep(&avr->ac_in);
167 av_freep(&avr->ac_out);
168 ff_audio_resample_free(&avr->resample);
169 ff_audio_mix_close(avr->am);
170 return;
171}
172
173void avresample_free(AVAudioResampleContext **avr)
174{
175 if (!*avr)
176 return;
177 avresample_close(*avr);
178 av_freep(&(*avr)->am);
179 av_opt_free(*avr);
180 av_freep(avr);
181}
182
183static int handle_buffered_output(AVAudioResampleContext *avr,
184 AudioData *output, AudioData *converted)
185{
186 int ret;
187
188 if (!output || av_audio_fifo_size(avr->out_fifo) > 0 ||
189 (converted && output->allocated_samples < converted->nb_samples)) {
190 if (converted) {
191 /* if there are any samples in the output FIFO or if the
192 user-supplied output buffer is not large enough for all samples,
193 we add to the output FIFO */
194 av_dlog(avr, "[FIFO] add %s to out_fifo\n", converted->name);
195 ret = ff_audio_data_add_to_fifo(avr->out_fifo, converted, 0,
196 converted->nb_samples);
197 if (ret < 0)
198 return ret;
199 }
200
201 /* if the user specified an output buffer, read samples from the output
202 FIFO to the user output */
203 if (output && output->allocated_samples > 0) {
204 av_dlog(avr, "[FIFO] read from out_fifo to output\n");
205 av_dlog(avr, "[end conversion]\n");
206 return ff_audio_data_read_from_fifo(avr->out_fifo, output,
207 output->allocated_samples);
208 }
209 } else if (converted) {
210 /* copy directly to output if it is large enough or there is not any
211 data in the output FIFO */
212 av_dlog(avr, "[copy] %s to output\n", converted->name);
213 output->nb_samples = 0;
214 ret = ff_audio_data_copy(output, converted);
215 if (ret < 0)
216 return ret;
217 av_dlog(avr, "[end conversion]\n");
218 return output->nb_samples;
219 }
220 av_dlog(avr, "[end conversion]\n");
221 return 0;
222}
223
224int avresample_convert(AVAudioResampleContext *avr, void **output,
225 int out_plane_size, int out_samples, void **input,
226 int in_plane_size, int in_samples)
227{
228 AudioData input_buffer;
229 AudioData output_buffer;
230 AudioData *current_buffer;
231 int ret;
232
233 /* reset internal buffers */
234 if (avr->in_buffer) {
235 avr->in_buffer->nb_samples = 0;
236 ff_audio_data_set_channels(avr->in_buffer,
237 avr->in_buffer->allocated_channels);
238 }
239 if (avr->resample_out_buffer) {
240 avr->resample_out_buffer->nb_samples = 0;
241 ff_audio_data_set_channels(avr->resample_out_buffer,
242 avr->resample_out_buffer->allocated_channels);
243 }
244 if (avr->out_buffer) {
245 avr->out_buffer->nb_samples = 0;
246 ff_audio_data_set_channels(avr->out_buffer,
247 avr->out_buffer->allocated_channels);
248 }
249
250 av_dlog(avr, "[start conversion]\n");
251
252 /* initialize output_buffer with output data */
253 if (output) {
254 ret = ff_audio_data_init(&output_buffer, output, out_plane_size,
255 avr->out_channels, out_samples,
256 avr->out_sample_fmt, 0, "output");
257 if (ret < 0)
258 return ret;
259 output_buffer.nb_samples = 0;
260 }
261
262 if (input) {
263 /* initialize input_buffer with input data */
264 ret = ff_audio_data_init(&input_buffer, input, in_plane_size,
265 avr->in_channels, in_samples,
266 avr->in_sample_fmt, 1, "input");
267 if (ret < 0)
268 return ret;
269 current_buffer = &input_buffer;
270
271 if (avr->upmix_needed && !avr->in_convert_needed && !avr->resample_needed &&
272 !avr->out_convert_needed && output && out_samples >= in_samples) {
273 /* in some rare cases we can copy input to output and upmix
274 directly in the output buffer */
275 av_dlog(avr, "[copy] %s to output\n", current_buffer->name);
276 ret = ff_audio_data_copy(&output_buffer, current_buffer);
277 if (ret < 0)
278 return ret;
279 current_buffer = &output_buffer;
280 } else if (avr->mixing_needed || avr->in_convert_needed) {
281 /* if needed, copy or convert input to in_buffer, and downmix if
282 applicable */
283 if (avr->in_convert_needed) {
284 ret = ff_audio_data_realloc(avr->in_buffer,
285 current_buffer->nb_samples);
286 if (ret < 0)
287 return ret;
288 av_dlog(avr, "[convert] %s to in_buffer\n", current_buffer->name);
289 ret = ff_audio_convert(avr->ac_in, avr->in_buffer, current_buffer,
290 current_buffer->nb_samples);
291 if (ret < 0)
292 return ret;
293 } else {
294 av_dlog(avr, "[copy] %s to in_buffer\n", current_buffer->name);
295 ret = ff_audio_data_copy(avr->in_buffer, current_buffer);
296 if (ret < 0)
297 return ret;
298 }
299 ff_audio_data_set_channels(avr->in_buffer, avr->in_channels);
300 if (avr->downmix_needed) {
301 av_dlog(avr, "[downmix] in_buffer\n");
302 ret = ff_audio_mix(avr->am, avr->in_buffer);
303 if (ret < 0)
304 return ret;
305 }
306 current_buffer = avr->in_buffer;
307 }
308 } else {
309 /* flush resampling buffer and/or output FIFO if input is NULL */
310 if (!avr->resample_needed)
311 return handle_buffered_output(avr, output ? &output_buffer : NULL,
312 NULL);
313 current_buffer = NULL;
314 }
315
316 if (avr->resample_needed) {
317 AudioData *resample_out;
318 int consumed = 0;
319
320 if (!avr->out_convert_needed && output && out_samples > 0)
321 resample_out = &output_buffer;
322 else
323 resample_out = avr->resample_out_buffer;
324 av_dlog(avr, "[resample] %s to %s\n", current_buffer->name,
325 resample_out->name);
326 ret = ff_audio_resample(avr->resample, resample_out,
327 current_buffer, &consumed);
328 if (ret < 0)
329 return ret;
330
331 /* if resampling did not produce any samples, just return 0 */
332 if (resample_out->nb_samples == 0) {
333 av_dlog(avr, "[end conversion]\n");
334 return 0;
335 }
336
337 current_buffer = resample_out;
338 }
339
340 if (avr->upmix_needed) {
341 av_dlog(avr, "[upmix] %s\n", current_buffer->name);
342 ret = ff_audio_mix(avr->am, current_buffer);
343 if (ret < 0)
344 return ret;
345 }
346
347 /* if we resampled or upmixed directly to output, return here */
348 if (current_buffer == &output_buffer) {
349 av_dlog(avr, "[end conversion]\n");
350 return current_buffer->nb_samples;
351 }
352
353 if (avr->out_convert_needed) {
354 if (output && out_samples >= current_buffer->nb_samples) {
355 /* convert directly to output */
356 av_dlog(avr, "[convert] %s to output\n", current_buffer->name);
357 ret = ff_audio_convert(avr->ac_out, &output_buffer, current_buffer,
358 current_buffer->nb_samples);
359 if (ret < 0)
360 return ret;
361
362 av_dlog(avr, "[end conversion]\n");
363 return output_buffer.nb_samples;
364 } else {
365 ret = ff_audio_data_realloc(avr->out_buffer,
366 current_buffer->nb_samples);
367 if (ret < 0)
368 return ret;
369 av_dlog(avr, "[convert] %s to out_buffer\n", current_buffer->name);
370 ret = ff_audio_convert(avr->ac_out, avr->out_buffer,
371 current_buffer, current_buffer->nb_samples);
372 if (ret < 0)
373 return ret;
374 current_buffer = avr->out_buffer;
375 }
376 }
377
378 return handle_buffered_output(avr, &output_buffer, current_buffer);
379}
380
381int avresample_available(AVAudioResampleContext *avr)
382{
383 return av_audio_fifo_size(avr->out_fifo);
384}
385
386int avresample_read(AVAudioResampleContext *avr, void **output, int nb_samples)
387{
388 return av_audio_fifo_read(avr->out_fifo, output, nb_samples);
389}
390
391unsigned avresample_version(void)
392{
393 return LIBAVRESAMPLE_VERSION_INT;
394}
395
396const char *avresample_license(void)
397{
398#define LICENSE_PREFIX "libavresample license: "
399 return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
400}
401
402const char *avresample_configuration(void)
403{
404 return FFMPEG_CONFIGURATION;
405}
libavresample/version.h+41−0
@@ -0,0 +1,41 @@
1/*
2 * This file is part of Libav.
3 *
4 * Libav is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * Libav is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with Libav; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#ifndef AVRESAMPLE_VERSION_H
20#define AVRESAMPLE_VERSION_H
21
22#define LIBAVRESAMPLE_VERSION_MAJOR 0
23#define LIBAVRESAMPLE_VERSION_MINOR 0
24#define LIBAVRESAMPLE_VERSION_MICRO 0
25
26#define LIBAVRESAMPLE_VERSION_INT AV_VERSION_INT(LIBAVRESAMPLE_VERSION_MAJOR, \
27 LIBAVRESAMPLE_VERSION_MINOR, \
28 LIBAVRESAMPLE_VERSION_MICRO)
29#define LIBAVRESAMPLE_VERSION AV_VERSION(LIBAVRESAMPLE_VERSION_MAJOR, \
30 LIBAVRESAMPLE_VERSION_MINOR, \
31 LIBAVRESAMPLE_VERSION_MICRO)
32#define LIBAVRESAMPLE_BUILD LIBAVRESAMPLE_VERSION_INT
33
34#define LIBAVRESAMPLE_IDENT "Lavr" AV_STRINGIFY(LIBAVRESAMPLE_VERSION)
35
36/**
37 * These FF_API_* defines are not part of public API.
38 * They may change, break or disappear at any time.
39 */
40
41#endif /* AVRESAMPLE_VERSION_H */
libavresample/x86/Makefile+5−0
@@ -0,0 +1,5 @@
1OBJS += x86/audio_convert_init.o \
2 x86/audio_mix_init.o
3
4YASM-OBJS += x86/audio_convert.o \
5 x86/audio_mix.o
libavresample/x86/audio_convert.asm+104−0
@@ -0,0 +1,104 @@
1;******************************************************************************
2;* x86 optimized Format Conversion Utils
3;* Copyright (c) 2008 Loren Merritt
4;*
5;* This file is part of Libav.
6;*
7;* Libav is free software; you can redistribute it and/or
8;* modify it under the terms of the GNU Lesser General Public
9;* License as published by the Free Software Foundation; either
10;* version 2.1 of the License, or (at your option) any later version.
11;*
12;* Libav is distributed in the hope that it will be useful,
13;* but WITHOUT ANY WARRANTY; without even the implied warranty of
14;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15;* Lesser General Public License for more details.
16;*
17;* You should have received a copy of the GNU Lesser General Public
18;* License along with Libav; if not, write to the Free Software
19;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20;******************************************************************************
21
22%include "x86inc.asm"
23%include "x86util.asm"
24
25SECTION_TEXT
26
27;-----------------------------------------------------------------------------
28; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len,
29; int channels);
30;-----------------------------------------------------------------------------
31
32%macro CONV_FLTP_TO_FLT_6CH 0
33cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
34%if ARCH_X86_64
35 mov lend, r2d
36%else
37 %define lend dword r2m
38%endif
39 mov src1q, [srcq+1*gprsize]
40 mov src2q, [srcq+2*gprsize]
41 mov src3q, [srcq+3*gprsize]
42 mov src4q, [srcq+4*gprsize]
43 mov src5q, [srcq+5*gprsize]
44 mov srcq, [srcq]
45 sub src1q, srcq
46 sub src2q, srcq
47 sub src3q, srcq
48 sub src4q, srcq
49 sub src5q, srcq
50.loop:
51 mova m0, [srcq ]
52 mova m1, [srcq+src1q]
53 mova m2, [srcq+src2q]
54 mova m3, [srcq+src3q]
55 mova m4, [srcq+src4q]
56 mova m5, [srcq+src5q]
57%if cpuflag(sse)
58 SBUTTERFLYPS 0, 1, 6
59 SBUTTERFLYPS 2, 3, 6
60 SBUTTERFLYPS 4, 5, 6
61
62 movaps m6, m4
63 shufps m4, m0, q3210
64 movlhps m0, m2
65 movhlps m6, m2
66 movaps [dstq ], m0
67 movaps [dstq+16], m4
68 movaps [dstq+32], m6
69
70 movaps m6, m5
71 shufps m5, m1, q3210
72 movlhps m1, m3
73 movhlps m6, m3
74 movaps [dstq+48], m1
75 movaps [dstq+64], m5
76 movaps [dstq+80], m6
77%else ; mmx
78 SBUTTERFLY dq, 0, 1, 6
79 SBUTTERFLY dq, 2, 3, 6
80 SBUTTERFLY dq, 4, 5, 6
81
82 movq [dstq ], m0
83 movq [dstq+ 8], m2
84 movq [dstq+16], m4
85 movq [dstq+24], m1
86 movq [dstq+32], m3
87 movq [dstq+40], m5
88%endif
89 add srcq, mmsize
90 add dstq, mmsize*6
91 sub lend, mmsize/4
92 jg .loop
93%if mmsize == 8
94 emms
95 RET
96%else
97 REP_RET
98%endif
99%endmacro
100
101INIT_MMX mmx
102CONV_FLTP_TO_FLT_6CH
103INIT_XMM sse
104CONV_FLTP_TO_FLT_6CH
libavresample/x86/audio_convert_init.c+42−0
@@ -0,0 +1,42 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22#include "libavutil/cpu.h"
23#include "libavresample/audio_convert.h"
24
25extern void ff_conv_fltp_to_flt_6ch_mmx(float *dst, float *const *src, int len);
26extern void ff_conv_fltp_to_flt_6ch_sse(float *dst, float *const *src, int len);
27
28av_cold void ff_audio_convert_init_x86(AudioConvert *ac)
29{
30#if HAVE_YASM
31 int mm_flags = av_get_cpu_flags();
32
33 if (mm_flags & AV_CPU_FLAG_MMX && HAVE_MMX) {
34 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
35 6, 1, 4, "MMX", ff_conv_fltp_to_flt_6ch_mmx);
36 }
37 if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) {
38 ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
39 6, 16, 4, "SSE", ff_conv_fltp_to_flt_6ch_sse);
40 }
41#endif
42}
libavresample/x86/audio_mix.asm+64−0
@@ -0,0 +1,64 @@
1;******************************************************************************
2;* x86 optimized channel mixing
3;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4;*
5;* This file is part of Libav.
6;*
7;* Libav is free software; you can redistribute it and/or
8;* modify it under the terms of the GNU Lesser General Public
9;* License as published by the Free Software Foundation; either
10;* version 2.1 of the License, or (at your option) any later version.
11;*
12;* Libav is distributed in the hope that it will be useful,
13;* but WITHOUT ANY WARRANTY; without even the implied warranty of
14;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15;* Lesser General Public License for more details.
16;*
17;* You should have received a copy of the GNU Lesser General Public
18;* License along with Libav; if not, write to the Free Software
19;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20;******************************************************************************
21
22%include "x86inc.asm"
23%include "x86util.asm"
24
25SECTION_TEXT
26
27;-----------------------------------------------------------------------------
28; void ff_mix_2_to_1_fltp_flt(float **src, float **matrix, int len,
29; int out_ch, int in_ch);
30;-----------------------------------------------------------------------------
31
32%macro MIX_2_TO_1_FLTP_FLT 0
33cglobal mix_2_to_1_fltp_flt, 3,4,6, src, matrix, len, src1
34 mov src1q, [srcq+gprsize]
35 mov srcq, [srcq ]
36 sub src1q, srcq
37 mov matrixq, [matrixq ]
38 VBROADCASTSS m4, [matrixq ]
39 VBROADCASTSS m5, [matrixq+4]
40 ALIGN 16
41.loop:
42 mulps m0, m4, [srcq ]
43 mulps m1, m5, [srcq+src1q ]
44 mulps m2, m4, [srcq+ mmsize]
45 mulps m3, m5, [srcq+src1q+mmsize]
46 addps m0, m0, m1
47 addps m2, m2, m3
48 mova [srcq ], m0
49 mova [srcq+mmsize], m2
50 add srcq, mmsize*2
51 sub lend, mmsize*2/4
52 jg .loop
53%if mmsize == 32
54 vzeroupper
55 RET
56%else
57 REP_RET
58%endif
59%endmacro
60
61INIT_XMM sse
62MIX_2_TO_1_FLTP_FLT
63INIT_YMM avx
64MIX_2_TO_1_FLTP_FLT
libavresample/x86/audio_mix_init.c+44−0
@@ -0,0 +1,44 @@
1/*
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3 *
4 * This file is part of Libav.
5 *
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22#include "libavutil/cpu.h"
23#include "libavresample/audio_mix.h"
24
25extern void ff_mix_2_to_1_fltp_flt_sse(float **src, float **matrix, int len,
26 int out_ch, int in_ch);
27extern void ff_mix_2_to_1_fltp_flt_avx(float **src, float **matrix, int len,
28 int out_ch, int in_ch);
29
30av_cold void ff_audio_mix_init_x86(AudioMix *am)
31{
32#if HAVE_YASM
33 int mm_flags = av_get_cpu_flags();
34
35 if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) {
36 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
37 2, 1, 16, 8, "SSE", ff_mix_2_to_1_fltp_flt_sse);
38 }
39 if (mm_flags & AV_CPU_FLAG_AVX && HAVE_AVX) {
40 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
41 2, 1, 32, 16, "AVX", ff_mix_2_to_1_fltp_flt_avx);
42 }
43#endif
44}
libavutil/x86/x86util.asm+9−0
@@ -585,3 +585,12 @@ · 584 unmodified lines
585 pminsd %1, %3585 pminsd %1, %3
586 pmaxsd %1, %2586 pmaxsd %1, %2
587%endmacro587%endmacro
588
589%macro VBROADCASTSS 2 ; dst xmm/ymm, src m32
590%if cpuflag(avx)
591 vbroadcastss %1, %2
592%else ; sse
593 movss %1, %2
594 shufps %1, %1, 0
595%endif
596%endmacro
tests/fate/aac.mak+2−2
@@ -55,8 +55,8 @@ fate-aac-ap05_48: CMD = pcm -i $(SAMPLES)/aac/ap05_48.mp4 · 54 unmodified lines
55fate-aac-ap05_48: REF = $(SAMPLES)/aac/ap05_48.s1655fate-aac-ap05_48: REF = $(SAMPLES)/aac/ap05_48.s16
56 56
57FATE_AAC += fate-aac-latm_stereo_to_5157FATE_AAC += fate-aac-latm_stereo_to_51
58fate-aac-latm_stereo_to_51: CMD = pcm -i $(SAMPLES)/aac/latm_stereo_to_51.ts -ac 658fate-aac-latm_stereo_to_51: CMD = pcm -i $(SAMPLES)/aac/latm_stereo_to_51.ts -channel_layout 5.1
59fate-aac-latm_stereo_to_51: REF = $(SAMPLES)/aac/latm_stereo_to_51.s1659fate-aac-latm_stereo_to_51: REF = $(SAMPLES)/aac/latm_stereo_to_51_ref.s16
60 60
61fate-aac-ct%: CMD = pcm -i $(SAMPLES)/aac/CT_DecoderCheck/$(@:fate-aac-ct-%=%)61fate-aac-ct%: CMD = pcm -i $(SAMPLES)/aac/CT_DecoderCheck/$(@:fate-aac-ct-%=%)
62fate-aac-ct%: REF = $(SAMPLES)/aac/CT_DecoderCheck/aacPlusv2.wav62fate-aac-ct%: REF = $(SAMPLES)/aac/CT_DecoderCheck/aacPlusv2.wav
tests/lavf-regression.sh+1−1
@@ -118,7 +118,7 @@ fi · 117 unmodified lines
118if [ -n "$do_dv_fmt" ] ; then118if [ -n "$do_dv_fmt" ] ; then
119do_lavf_timecode_nodrop dv "-ar 48000 -r 25 -s pal -ac 2"119do_lavf_timecode_nodrop dv "-ar 48000 -r 25 -s pal -ac 2"
120do_lavf_timecode_drop dv "-ar 48000 -pix_fmt yuv411p -s ntsc -ac 2"120do_lavf_timecode_drop dv "-ar 48000 -pix_fmt yuv411p -s ntsc -ac 2"
121do_lavf dv "-ar 48000" "-r 25 -s pal -ac 2"121do_lavf dv "-ar 48000 -channel_layout stereo" "-r 25 -s pal"
122fi122fi
123 123
124if [ -n "$do_gxf" ] ; then124if [ -n "$do_gxf" ] ; then
tests/ref/lavf/dv_fmt+2−2
@@ -4,6 +4,6 @@ · 3 unmodified lines
4cc33ae4f9e6828914dea0f09d1241b7e *./tests/data/lavf/lavf.dv4cc33ae4f9e6828914dea0f09d1241b7e *./tests/data/lavf/lavf.dv
53480000 ./tests/data/lavf/lavf.dv53480000 ./tests/data/lavf/lavf.dv
6./tests/data/lavf/lavf.dv CRC=0x8d5e9e8f6./tests/data/lavf/lavf.dv CRC=0x8d5e9e8f
7b36c83cd0ba0ebe719f09f885c4bbcd3 *./tests/data/lavf/lavf.dv787d3b20f656235671383a7eaa2f66330 *./tests/data/lavf/lavf.dv
83600000 ./tests/data/lavf/lavf.dv83600000 ./tests/data/lavf/lavf.dv
9./tests/data/lavf/lavf.dv CRC=0x2bc2ae3a9./tests/data/lavf/lavf.dv CRC=0x0e868a82

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t