浏览代码

add audio resampling, add ffmpeg support

jp9000 12 年之前
父节点
当前提交
60e6ddbf71

+ 8 - 0
configure.ac

@@ -40,6 +40,14 @@ case $host_os in
 		;;
 esac
 
+PKG_CHECK_MODULES([ffmpeg],
+		  [libavcodec
+		   libavformat
+		   libavutil
+		   libswscale
+		   libswresample
+		   libavfilter])
+
 # Checks for header files.
 AC_PATH_X
 AC_CHECK_HEADERS([inttypes.h limits.h malloc.h stddef.h stdint.h stdlib.h string.h sys/timeb.h wchar.h wctype.h])

+ 1 - 0
libobs/makefile.am

@@ -24,6 +24,7 @@ libobs_la_SOURCES = obs.c \
 		    util/utf8.c \
 		    media-io/audio-io.c \
 		    media-io/format-conversion.c \
+		    media-io/audio-resampler-ffmpeg.c \
 		    media-io/media-io.c \
 		    media-io/video-io.c \
 		    graphics/axisang.c \

+ 16 - 19
libobs/media-io/audio-io.h

@@ -34,16 +34,15 @@ struct audio_line;
 typedef struct audio_output *audio_t;
 typedef struct audio_line   *audio_line_t;
 
-enum audio_type {
+enum audio_format {
 	AUDIO_FORMAT_UNKNOWN,
-	AUDIO_FORMAT_8BIT,
+	AUDIO_FORMAT_U8BIT,
 	AUDIO_FORMAT_16BIT,
-	AUDIO_FORMAT_24BIT,
 	AUDIO_FORMAT_32BIT,
 	AUDIO_FORMAT_FLOAT,
 };
 
-enum speaker_setup {
+enum speaker_layout {
 	SPEAKERS_UNKNOWN,
 	SPEAKERS_MONO,
 	SPEAKERS_STEREO,
@@ -58,22 +57,21 @@ enum speaker_setup {
 };
 
 struct audio_data {
-	const void      *data;
-	uint32_t        frames;
-	uint64_t        timestamp;
+	const void          *data;
+	uint32_t            frames;
+	uint64_t            timestamp;
 };
 
 struct audio_info {
-	const char         *name;
-	const char         *format;
+	const char          *name;
+	const char          *format;
 
-	uint32_t           samples_per_sec;
-	enum audio_type    type;
-	enum speaker_setup speakers;
+	uint32_t            samples_per_sec;
+	enum audio_format   type;
+	enum speaker_layout speakers;
 };
 
-
-static inline uint32_t get_audio_channels(enum speaker_setup speakers)
+static inline uint32_t get_audio_channels(enum speaker_layout speakers)
 {
 	switch (speakers) {
 	case SPEAKERS_MONO:             return 1;
@@ -92,12 +90,11 @@ static inline uint32_t get_audio_channels(enum speaker_setup speakers)
 	return 0;
 }
 
-static inline size_t get_audio_bytes_per_channel(enum audio_type type)
+static inline size_t get_audio_bytes_per_channel(enum audio_format type)
 {
 	switch (type) {
-	case AUDIO_FORMAT_8BIT:    return 1;
+	case AUDIO_FORMAT_U8BIT:   return 1;
 	case AUDIO_FORMAT_16BIT:   return 2;
-	case AUDIO_FORMAT_24BIT:   return 3;
 	case AUDIO_FORMAT_FLOAT:
 	case AUDIO_FORMAT_32BIT:   return 4;
 	case AUDIO_FORMAT_UNKNOWN: return 0;
@@ -106,8 +103,8 @@ static inline size_t get_audio_bytes_per_channel(enum audio_type type)
 	return 0;
 }
 
-static inline size_t get_audio_size(enum audio_type type,
-		enum speaker_setup speakers, uint32_t frames)
+static inline size_t get_audio_size(enum audio_format type,
+		enum speaker_layout speakers, uint32_t frames)
 {
 	return get_audio_channels(speakers) *
 	       get_audio_bytes_per_channel(type) *

+ 170 - 0
libobs/media-io/audio-resampler-ffmpeg.c

@@ -0,0 +1,170 @@
+/******************************************************************************
+    Copyright (C) 2013 by Hugh Bailey <[email protected]>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#include "../util/bmem.h"
+#include "audio-resampler.h"
+#include <libswresample/swresample.h>
+#include <libavutil/channel_layout.h>
+#include <libavutil/opt.h>
+
+struct audio_resampler {
+	struct SwrContext   *context;
+	bool                opened;
+
+	uint32_t            input_freq;
+	uint64_t            input_layout;
+	enum AVSampleFormat input_format;
+
+	uint8_t             *output_buffer;
+	uint64_t            output_layout;
+	enum AVSampleFormat output_format;
+	int                 output_size;
+	uint32_t            output_ch;
+	uint32_t            output_freq;
+};
+
+static inline enum AVSampleFormat convert_audio_format(enum audio_format format)
+{
+	switch (format) {
+	case AUDIO_FORMAT_UNKNOWN: return AV_SAMPLE_FMT_S16;
+	case AUDIO_FORMAT_U8BIT:   return AV_SAMPLE_FMT_U8;
+	case AUDIO_FORMAT_16BIT:   return AV_SAMPLE_FMT_S16;
+	case AUDIO_FORMAT_32BIT:   return AV_SAMPLE_FMT_S32;
+	case AUDIO_FORMAT_FLOAT:   return AV_SAMPLE_FMT_FLT;
+	}
+
+	/* shouldn't get here */
+	return AV_SAMPLE_FMT_S16;
+}
+
+static inline uint64_t convert_speaker_layout(enum speaker_layout layout)
+{
+	switch (layout) {
+	case SPEAKERS_UNKNOWN:          return 0;
+	case SPEAKERS_MONO:             return AV_CH_LAYOUT_MONO;
+	case SPEAKERS_STEREO:           return AV_CH_LAYOUT_STEREO;
+	case SPEAKERS_2POINT1:          return AV_CH_LAYOUT_2_1;
+	case SPEAKERS_QUAD:             return AV_CH_LAYOUT_QUAD;
+	case SPEAKERS_4POINT1:          return AV_CH_LAYOUT_4POINT1;
+	case SPEAKERS_5POINT1:          return AV_CH_LAYOUT_5POINT1;
+	case SPEAKERS_5POINT1_SURROUND: return AV_CH_LAYOUT_5POINT1_BACK;
+	case SPEAKERS_7POINT1:          return AV_CH_LAYOUT_7POINT1;
+	case SPEAKERS_7POINT1_SURROUND: return AV_CH_LAYOUT_7POINT1_WIDE_BACK;
+	case SPEAKERS_SURROUND:         return AV_CH_LAYOUT_SURROUND;
+	}
+
+	/* shouldn't get here */
+	return 0;
+}
+
+audio_resampler_t audio_resampler_create(struct resample_info *dst,
+		struct resample_info *src)
+{
+	struct audio_resampler *rs = bmalloc(sizeof(struct audio_resampler));
+	int errcode;
+
+	rs->opened        = false;
+	rs->input_freq    = src->samples_per_sec;
+	rs->input_layout  = convert_speaker_layout(src->speakers);
+	rs->input_format  = convert_audio_format(src->format);
+	rs->output_buffer = NULL;
+	rs->output_size   = 0;
+	rs->output_ch     = get_audio_channels(dst->speakers);
+	rs->output_freq   = dst->samples_per_sec;
+	rs->output_layout = convert_speaker_layout(dst->speakers);
+	rs->output_format = convert_audio_format(dst->format);
+
+	rs->context = swr_alloc_set_opts(NULL,
+		rs->output_layout, rs->output_format, dst->samples_per_sec,
+		rs->input_layout,  rs->input_format,  src->samples_per_sec,
+		0, NULL);
+
+	if (!rs->context) {
+		blog(LOG_ERROR, "swr_alloc_set_opts failed");
+		audio_resampler_destroy(rs);
+		return NULL;
+	}
+
+	av_opt_set_channel_layout(rs->context, "in_channel_layout",
+			rs->input_layout, 0);
+	av_opt_set_channel_layout(rs->context, "out_channel_layout",
+			rs->output_layout, 0);
+	av_opt_set_int(rs->context, "in_sample_rate",  src->samples_per_sec, 0);
+	av_opt_set_int(rs->context, "out_sample_rate", dst->samples_per_sec, 0);
+	av_opt_set_sample_fmt(rs->context, "in_sample_fmt",
+			rs->input_format, 0);
+	av_opt_set_sample_fmt(rs->context, "out_sample_fmt",
+			rs->output_format, 0);
+
+	errcode = swr_init(rs->context);
+	if (errcode != 0) {
+		blog(LOG_ERROR, "avresample_open failed: error code %d",
+				errcode);
+		audio_resampler_destroy(rs);
+		return NULL;
+	}
+
+	return rs;
+}
+
+void audio_resampler_destroy(audio_resampler_t rs)
+{
+	if (rs) {
+		if (rs->context)
+			swr_free(&rs->context);
+		if (rs->output_buffer)
+			av_freep(&rs->output_buffer);
+
+		bfree(rs);
+	}
+}
+
+bool audio_resampler_resample(audio_resampler_t rs,
+		 void **output, uint32_t *out_frames,
+		 void *input, uint32_t in_frames)
+{
+	struct SwrContext *context = rs->context;
+	int ret;
+	int64_t delay = swr_get_delay(context, rs->input_freq);
+	int estimated = (int)av_rescale_rnd(
+			delay + (int64_t)in_frames,
+			(int64_t)rs->output_freq, (int64_t)rs->input_freq,
+			AV_ROUND_UP);
+
+	/* resize the buffer if bigger */
+	if (estimated > rs->output_size) {
+		if (rs->output_buffer)
+			av_freep(&rs->output_buffer);
+		av_samples_alloc(&rs->output_buffer, NULL, rs->output_ch,
+				estimated, rs->output_format, 0);
+
+		rs->output_size = estimated;
+	}
+
+	ret = swr_convert(context,
+			&rs->output_buffer, rs->output_size,
+			input, in_frames);
+
+	if (ret < 0) {
+		blog(LOG_ERROR, "swr_convert failed: %d", ret);
+		return false;
+	}
+
+	*output     = rs->output_buffer;
+	*out_frames = (uint32_t)ret;
+	return true;
+}

+ 38 - 0
libobs/media-io/audio-resampler.h

@@ -0,0 +1,38 @@
+/******************************************************************************
+    Copyright (C) 2013 by Hugh Bailey <[email protected]>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+******************************************************************************/
+
+#pragma once
+
+#include "../util/c99defs.h"
+#include "audio-io.h"
+
+struct audio_resampler;
+typedef struct audio_resampler *audio_resampler_t;
+
+struct resample_info {
+	uint32_t            samples_per_sec;
+	enum audio_format   format;
+	enum speaker_layout speakers;
+};
+
+EXPORT audio_resampler_t audio_resampler_create(struct resample_info *dst,
+		struct resample_info *src);
+EXPORT void audio_resampler_destroy(audio_resampler_t resampler);
+
+EXPORT bool audio_resampler_resample(audio_resampler_t resampler,
+		 void **output, uint32_t *out_frames,
+		 void *input, uint32_t in_frames);

+ 15 - 15
libobs/obs.h

@@ -49,28 +49,28 @@ enum order_movement {
 };
 
 struct source_audio {
-	const void         *data;
-	uint32_t           frames;
+	const void          *data;
+	uint32_t            frames;
 
 	/* audio will be automatically resampled/upmixed/downmixed */
-	enum speaker_setup speakers;
-	enum audio_type    type;
-	uint32_t           samples_per_sec;
+	enum speaker_layout speakers;
+	enum audio_format   type;
+	uint32_t            samples_per_sec;
 
 	/* can be 0 if 'immediate' */
-	uint64_t           timestamp;
+	uint64_t            timestamp;
 };
 
 struct source_frame {
-	void               *data;
-	uint32_t           width;
-	uint32_t           height;
-	uint32_t           row_bytes;
-	uint64_t           timestamp;
-
-	enum video_type    type;
-	float              yuv_matrix[16];
-	bool               flip;
+	void                *data;
+	uint32_t            width;
+	uint32_t            height;
+	uint32_t            row_bytes;
+	uint64_t            timestamp;
+
+	enum video_type     type;
+	float               yuv_matrix[16];
+	bool                flip;
 };
 
 static inline void source_frame_destroy(struct source_frame *frame)

+ 285 - 0
libobs/util/vc/inttypes.h

@@ -0,0 +1,285 @@
+// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+//  Copyright (c) 2006 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+//
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+//
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+   intmax_t quot;
+   intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8       "d"
+#define PRIi8       "i"
+#define PRIdLEAST8  "d"
+#define PRIiLEAST8  "i"
+#define PRIdFAST8   "d"
+#define PRIiFAST8   "i"
+
+#define PRId16       "hd"
+#define PRIi16       "hi"
+#define PRIdLEAST16  "hd"
+#define PRIiLEAST16  "hi"
+#define PRIdFAST16   "hd"
+#define PRIiFAST16   "hi"
+
+#define PRId32       "I32d"
+#define PRIi32       "I32i"
+#define PRIdLEAST32  "I32d"
+#define PRIiLEAST32  "I32i"
+#define PRIdFAST32   "I32d"
+#define PRIiFAST32   "I32i"
+
+#define PRId64       "I64d"
+#define PRIi64       "I64i"
+#define PRIdLEAST64  "I64d"
+#define PRIiLEAST64  "I64i"
+#define PRIdFAST64   "I64d"
+#define PRIiFAST64   "I64i"
+
+#define PRIdMAX     "I64d"
+#define PRIiMAX     "I64i"
+
+#define PRIdPTR     "Id"
+#define PRIiPTR     "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8       "o"
+#define PRIu8       "u"
+#define PRIx8       "x"
+#define PRIX8       "X"
+#define PRIoLEAST8  "o"
+#define PRIuLEAST8  "u"
+#define PRIxLEAST8  "x"
+#define PRIXLEAST8  "X"
+#define PRIoFAST8   "o"
+#define PRIuFAST8   "u"
+#define PRIxFAST8   "x"
+#define PRIXFAST8   "X"
+
+#define PRIo16       "ho"
+#define PRIu16       "hu"
+#define PRIx16       "hx"
+#define PRIX16       "hX"
+#define PRIoLEAST16  "ho"
+#define PRIuLEAST16  "hu"
+#define PRIxLEAST16  "hx"
+#define PRIXLEAST16  "hX"
+#define PRIoFAST16   "ho"
+#define PRIuFAST16   "hu"
+#define PRIxFAST16   "hx"
+#define PRIXFAST16   "hX"
+
+#define PRIo32       "I32o"
+#define PRIu32       "I32u"
+#define PRIx32       "I32x"
+#define PRIX32       "I32X"
+#define PRIoLEAST32  "I32o"
+#define PRIuLEAST32  "I32u"
+#define PRIxLEAST32  "I32x"
+#define PRIXLEAST32  "I32X"
+#define PRIoFAST32   "I32o"
+#define PRIuFAST32   "I32u"
+#define PRIxFAST32   "I32x"
+#define PRIXFAST32   "I32X"
+
+#define PRIo64       "I64o"
+#define PRIu64       "I64u"
+#define PRIx64       "I64x"
+#define PRIX64       "I64X"
+#define PRIoLEAST64  "I64o"
+#define PRIuLEAST64  "I64u"
+#define PRIxLEAST64  "I64x"
+#define PRIXLEAST64  "I64X"
+#define PRIoFAST64   "I64o"
+#define PRIuFAST64   "I64u"
+#define PRIxFAST64   "I64x"
+#define PRIXFAST64   "I64X"
+
+#define PRIoMAX     "I64o"
+#define PRIuMAX     "I64u"
+#define PRIxMAX     "I64x"
+#define PRIXMAX     "I64X"
+
+#define PRIoPTR     "Io"
+#define PRIuPTR     "Iu"
+#define PRIxPTR     "Ix"
+#define PRIXPTR     "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd16       "hd"
+#define SCNi16       "hi"
+#define SCNdLEAST16  "hd"
+#define SCNiLEAST16  "hi"
+#define SCNdFAST16   "hd"
+#define SCNiFAST16   "hi"
+
+#define SCNd32       "ld"
+#define SCNi32       "li"
+#define SCNdLEAST32  "ld"
+#define SCNiLEAST32  "li"
+#define SCNdFAST32   "ld"
+#define SCNiFAST32   "li"
+
+#define SCNd64       "I64d"
+#define SCNi64       "I64i"
+#define SCNdLEAST64  "I64d"
+#define SCNiLEAST64  "I64i"
+#define SCNdFAST64   "I64d"
+#define SCNiFAST64   "I64i"
+
+#define SCNdMAX     "I64d"
+#define SCNiMAX     "I64i"
+
+#ifdef _WIN64 // [
+#  define SCNdPTR     "I64d"
+#  define SCNiPTR     "I64i"
+#else  // _WIN64 ][
+#  define SCNdPTR     "ld"
+#  define SCNiPTR     "li"
+#endif  // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo16       "ho"
+#define SCNu16       "hu"
+#define SCNx16       "hx"
+#define SCNX16       "hX"
+#define SCNoLEAST16  "ho"
+#define SCNuLEAST16  "hu"
+#define SCNxLEAST16  "hx"
+#define SCNXLEAST16  "hX"
+#define SCNoFAST16   "ho"
+#define SCNuFAST16   "hu"
+#define SCNxFAST16   "hx"
+#define SCNXFAST16   "hX"
+
+#define SCNo32       "lo"
+#define SCNu32       "lu"
+#define SCNx32       "lx"
+#define SCNX32       "lX"
+#define SCNoLEAST32  "lo"
+#define SCNuLEAST32  "lu"
+#define SCNxLEAST32  "lx"
+#define SCNXLEAST32  "lX"
+#define SCNoFAST32   "lo"
+#define SCNuFAST32   "lu"
+#define SCNxFAST32   "lx"
+#define SCNXFAST32   "lX"
+
+#define SCNo64       "I64o"
+#define SCNu64       "I64u"
+#define SCNx64       "I64x"
+#define SCNX64       "I64X"
+#define SCNoLEAST64  "I64o"
+#define SCNuLEAST64  "I64u"
+#define SCNxLEAST64  "I64x"
+#define SCNXLEAST64  "I64X"
+#define SCNoFAST64   "I64o"
+#define SCNuFAST64   "I64u"
+#define SCNxFAST64   "I64x"
+#define SCNXFAST64   "I64X"
+
+#define SCNoMAX     "I64o"
+#define SCNuMAX     "I64u"
+#define SCNxMAX     "I64x"
+#define SCNXMAX     "I64X"
+
+#ifdef _WIN64 // [
+#  define SCNoPTR     "I64o"
+#  define SCNuPTR     "I64u"
+#  define SCNxPTR     "I64x"
+#  define SCNXPTR     "I64X"
+#else  // _WIN64 ][
+#  define SCNoPTR     "lo"
+#  define SCNuPTR     "lu"
+#  define SCNxPTR     "lx"
+#  define SCNXPTR     "lX"
+#endif  // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+   imaxdiv_t result;
+
+   result.quot = numer / denom;
+   result.rem = numer % denom;
+
+   if (numer < 0 && result.rem > 0) {
+      // did division wrong; must fix up
+      ++result.quot;
+      result.rem -= denom;
+   }
+
+   return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+
+#endif // _MSC_INTTYPES_H_ ]

+ 18 - 4
vs/2010/libobs/libobs.vcxproj

@@ -37,6 +37,7 @@
     <ClInclude Include="..\..\..\libobs\graphics\vec3.h" />
     <ClInclude Include="..\..\..\libobs\graphics\vec4.h" />
     <ClInclude Include="..\..\..\libobs\media-io\audio-io.h" />
+    <ClInclude Include="..\..\..\libobs\media-io\audio-resampler.h" />
     <ClInclude Include="..\..\..\libobs\media-io\format-conversion.h" />
     <ClInclude Include="..\..\..\libobs\media-io\media-io.h" />
     <ClInclude Include="..\..\..\libobs\media-io\video-io.h" />
@@ -81,6 +82,7 @@
     <ClCompile Include="..\..\..\libobs\graphics\vec3.c" />
     <ClCompile Include="..\..\..\libobs\graphics\vec4.c" />
     <ClCompile Include="..\..\..\libobs\media-io\audio-io.c" />
+    <ClCompile Include="..\..\..\libobs\media-io\audio-resampler-ffmpeg.c" />
     <ClCompile Include="..\..\..\libobs\media-io\format-conversion.c" />
     <ClCompile Include="..\..\..\libobs\media-io\media-io.c" />
     <ClCompile Include="..\..\..\libobs\media-io\video-io.c" />
@@ -149,15 +151,23 @@
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <LinkIncremental>true</LinkIncremental>
+    <IncludePath>$(FFmpegPath);$(IncludePath)</IncludePath>
+    <LibraryPath>$(FFmpegPath)\lib32;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <LinkIncremental>true</LinkIncremental>
+    <IncludePath>$(FFmpegPath);$(IncludePath)</IncludePath>
+    <LibraryPath>$(FFmpegPath)\lib64;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <LinkIncremental>false</LinkIncremental>
+    <IncludePath>$(FFmpegPath);$(IncludePath)</IncludePath>
+    <LibraryPath>$(FFmpegPath)\lib32;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
     <LinkIncremental>false</LinkIncremental>
+    <IncludePath>$(FFmpegPath);$(IncludePath)</IncludePath>
+    <LibraryPath>$(FFmpegPath)\lib64;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
@@ -168,11 +178,12 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBOBS_EXPORTS;PTW32_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>false</ExceptionHandling>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <AdditionalIncludeDirectories>../../../libobs/util/vc</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>pthreads.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>avutil.lib;swresample.lib;pthreads.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
     <PostBuildEvent>
@@ -188,11 +199,12 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBOBS_EXPORTS;PTW32_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>false</ExceptionHandling>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <AdditionalIncludeDirectories>../../../libobs/util/vc</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>pthreads.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>avutil.lib;swresample.lib;pthreads.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
     <PostBuildEvent>
@@ -210,13 +222,14 @@
       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBOBS_EXPORTS;PTW32_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>false</ExceptionHandling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <AdditionalIncludeDirectories>../../../libobs/util/vc</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>pthreads.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>avutil.lib;swresample.lib;pthreads.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
     <PostBuildEvent>
@@ -234,13 +247,14 @@
       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBOBS_EXPORTS;PTW32_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>false</ExceptionHandling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <AdditionalIncludeDirectories>../../../libobs/util/vc</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>pthreads.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>avutil.lib;swresample.lib;pthreads.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
     <PostBuildEvent>

+ 6 - 0
vs/2010/libobs/libobs.vcxproj.filters

@@ -180,6 +180,9 @@
     <ClInclude Include="..\..\..\libobs\media-io\format-conversion.h">
       <Filter>media-io\Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\libobs\media-io\audio-resampler.h">
+      <Filter>media-io\Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\libobs\obs-output.c">
@@ -296,5 +299,8 @@
     <ClCompile Include="..\..\..\libobs\media-io\format-conversion.c">
       <Filter>media-io\Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\libobs\media-io\audio-resampler-ffmpeg.c">
+      <Filter>media-io\Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>