summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2012-07-26 22:17:58 +0100
committerCarl Hetherington <cth@carlh.net>2012-07-26 22:17:58 +0100
commit4928ece9b10df775ab3003c024f52bdd30d8f591 (patch)
tree6a0b3c008c33386e2d2ebae4b9aa59ea83149cee /src/lib
parent466037c8c1cd4bdb07b959b844e83a511b3bfcfa (diff)
Implemented but faulty.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/decoder.cc86
-rw-r--r--src/lib/decoder.h9
-rw-r--r--src/lib/ffmpeg_decoder.cc6
-rw-r--r--src/lib/ffmpeg_decoder.h1
-rw-r--r--src/lib/film_state.h2
-rw-r--r--src/lib/imagemagick_decoder.h4
-rw-r--r--src/lib/j2k_wav_encoder.cc2
-rw-r--r--src/lib/tiff_decoder.cc8
-rw-r--r--src/lib/tiff_decoder.h1
-rw-r--r--src/lib/util.cc10
-rw-r--r--src/lib/util.h2
11 files changed, 121 insertions, 10 deletions
diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc
index 9cbd93405..efa37672b 100644
--- a/src/lib/decoder.cc
+++ b/src/lib/decoder.cc
@@ -32,6 +32,7 @@ extern "C" {
#endif
#include <libavformat/avio.h>
}
+#include <samplerate.h>
#include "film.h"
#include "format.h"
#include "job.h"
@@ -67,6 +68,7 @@ Decoder::Decoder (boost::shared_ptr<const FilmState> s, boost::shared_ptr<const
, _video_frame (0)
, _buffer_src_context (0)
, _buffer_sink_context (0)
+ , _swr_context (0)
, _have_setup_video_filters (false)
, _delay_line (0)
, _delay_in_bytes (0)
@@ -85,6 +87,23 @@ Decoder::~Decoder ()
void
Decoder::process_begin ()
{
+ if (_fs->audio_sample_rate != dcp_audio_sample_rate (_fs->audio_sample_rate)) {
+ _swr_context = swr_alloc_set_opts (
+ 0,
+ audio_channel_layout(),
+ audio_sample_format(),
+ dcp_audio_sample_rate (_fs->audio_sample_rate),
+ audio_channel_layout(),
+ audio_sample_format(),
+ _fs->audio_sample_rate,
+ 0, 0
+ );
+
+ swr_init (_swr_context);
+ } else {
+ _swr_context = 0;
+ }
+
/* This assumes 2 bytes per sample */
_delay_in_bytes = _fs->audio_delay * _fs->audio_sample_rate * _fs->audio_channels * 2 / 1000;
delete _delay_line;
@@ -96,6 +115,35 @@ Decoder::process_begin ()
void
Decoder::process_end ()
{
+ if (_swr_context) {
+
+ int mop = 0;
+ while (1) {
+ uint8_t buffer[256 * 2 * _fs->audio_channels];
+ uint8_t* out[1] = {
+ buffer
+ };
+
+ int const frames = swr_convert (_swr_context, out, 256, 0, 0);
+
+ if (frames < 0) {
+ throw DecodeError ("could not run sample-rate converter");
+ }
+
+ if (frames == 0) {
+ break;
+ }
+
+ mop += frames;
+ int available = _delay_line->feed (buffer, frames * _fs->audio_channels * 2);
+ Audio (buffer, available);
+ }
+
+ cout << "mopped up " << mop << "\n";
+
+ swr_free (&_swr_context);
+ }
+
if (_delay_in_bytes < 0) {
uint8_t remainder[-_delay_in_bytes];
_delay_line->get_remaining (remainder);
@@ -107,7 +155,7 @@ Decoder::process_end ()
in to get it to the right length.
*/
- int const audio_short_by_frames = (decoding_frames() * _fs->audio_sample_rate / _fs->frames_per_second) - _audio_frames_processed;
+ int const audio_short_by_frames = (decoding_frames() * dcp_audio_sample_rate (_fs->audio_sample_rate) / _fs->frames_per_second) - _audio_frames_processed;
int bytes = audio_short_by_frames * audio_channels() * 2;
@@ -175,15 +223,12 @@ Decoder::pass ()
void
Decoder::process_audio (uint8_t* data, int channels, int size)
{
- /* Update the number of audio frames we've pushed to the encoder;
- 2 is the hard-coded (!) number of bytes per sample.
- */
- _audio_frames_processed += size / (channels * 2);
-
+ int const samples = size / 2;
+ int const frames = samples / channels;
+
if (_fs->audio_gain != 0) {
float const linear_gain = pow (10, _fs->audio_gain / 20);
uint8_t* p = data;
- int const samples = size / 2;
switch (_fs->audio_sample_format) {
case AV_SAMPLE_FMT_S16:
for (int i = 0; i < samples; ++i) {
@@ -202,6 +247,33 @@ Decoder::process_audio (uint8_t* data, int channels, int size)
}
}
+ if (_swr_context) {
+
+ uint8_t const * in[1] = {
+ data
+ };
+
+ int const out_buffer_size_frames = ceil (frames * float (dcp_audio_sample_rate (_fs->audio_sample_rate)) / _fs->audio_sample_rate) + 32;
+ int const out_buffer_size_bytes = out_buffer_size_frames * channels * 2;
+ uint8_t out_buffer[out_buffer_size_bytes];
+
+ uint8_t* out[1] = {
+ out_buffer
+ };
+
+ int out_frames = swr_convert (_swr_context, out, out_buffer_size_frames, in, frames);
+ if (out_frames < 0) {
+ throw DecodeError ("could not run sample-rate converter");
+ }
+
+ size = out_frames * channels * 2;
+ }
+
+ /* Update the number of audio frames we've pushed to the encoder;
+ 2 is the hard-coded (!) number of bytes per sample.
+ */
+ _audio_frames_processed += size / (channels * 2);
+
int available = _delay_line->feed (data, size);
Audio (data, available);
}
diff --git a/src/lib/decoder.h b/src/lib/decoder.h
index d85510470..198dfb8dc 100644
--- a/src/lib/decoder.h
+++ b/src/lib/decoder.h
@@ -29,6 +29,9 @@
#include <stdint.h>
#include <boost/shared_ptr.hpp>
#include <sigc++/sigc++.h>
+extern "C" {
+#include <libswresample/swresample.h>
+}
#include "util.h"
class Job;
@@ -65,6 +68,7 @@ public:
virtual int audio_sample_rate () const = 0;
/** @return format of audio samples */
virtual AVSampleFormat audio_sample_format () const = 0;
+ virtual int64_t audio_channel_layout () const = 0;
void process_begin ();
bool pass ();
@@ -128,10 +132,15 @@ private:
AVFilterContext* _buffer_src_context;
AVFilterContext* _buffer_sink_context;
+ SwrContext* _swr_context;
+
bool _have_setup_video_filters;
DelayLine* _delay_line;
int _delay_in_bytes;
+ /* Number of audio frames that we have pushed to the encoder
+ (at the DCP sample rate).
+ */
int _audio_frames_processed;
};
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index af258f381..df7434ff8 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -218,6 +218,12 @@ FFmpegDecoder::audio_sample_format () const
return _audio_codec_context->sample_fmt;
}
+int64_t
+FFmpegDecoder::audio_channel_layout () const
+{
+ return _audio_codec_context->channel_layout;
+}
+
Size
FFmpegDecoder::native_size () const
{
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index d66acad48..8e7d68580 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -62,6 +62,7 @@ public:
int audio_channels () const;
int audio_sample_rate () const;
AVSampleFormat audio_sample_format () const;
+ int64_t audio_channel_layout () const;
private:
diff --git a/src/lib/film_state.h b/src/lib/film_state.h
index 3a547ed1d..f4ccf37fd 100644
--- a/src/lib/film_state.h
+++ b/src/lib/film_state.h
@@ -143,7 +143,7 @@ public:
int length;
/** Number of audio channels */
int audio_channels;
- /** Sample rate of the audio, in Hz */
+ /** Sample rate of the source audio, in Hz */
int audio_sample_rate;
/** Format of the audio samples */
AVSampleFormat audio_sample_format;
diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h
index 707e6cacd..aca91ef55 100644
--- a/src/lib/imagemagick_decoder.h
+++ b/src/lib/imagemagick_decoder.h
@@ -31,6 +31,10 @@ public:
return AV_SAMPLE_FMT_NONE;
}
+ int64_t audio_channel_layout () const {
+ return 0;
+ }
+
static float static_frames_per_second () {
return 24;
}
diff --git a/src/lib/j2k_wav_encoder.cc b/src/lib/j2k_wav_encoder.cc
index b0881daf2..3bcb1e5fd 100644
--- a/src/lib/j2k_wav_encoder.cc
+++ b/src/lib/j2k_wav_encoder.cc
@@ -54,7 +54,7 @@ J2KWAVEncoder::J2KWAVEncoder (shared_ptr<const FilmState> s, shared_ptr<const Op
*/
for (int i = 0; i < _fs->audio_channels; ++i) {
SF_INFO sf_info;
- sf_info.samplerate = _fs->audio_sample_rate;
+ sf_info.samplerate = dcp_audio_sample_rate (_fs->audio_sample_rate);
/* We write mono files */
sf_info.channels = 1;
sf_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
diff --git a/src/lib/tiff_decoder.cc b/src/lib/tiff_decoder.cc
index 6738de49b..101e0c047 100644
--- a/src/lib/tiff_decoder.cc
+++ b/src/lib/tiff_decoder.cc
@@ -130,6 +130,13 @@ TIFFDecoder::audio_sample_format () const
return AV_SAMPLE_FMT_NONE;
}
+
+int64_t
+TIFFDecoder::audio_channel_layout () const
+{
+ return 0;
+}
+
bool
TIFFDecoder::do_pass ()
{
@@ -221,4 +228,3 @@ TIFFDecoder::sample_aspect_ratio_denominator () const
/* XXX */
return 1;
}
-
diff --git a/src/lib/tiff_decoder.h b/src/lib/tiff_decoder.h
index dbd76f36d..d9b5b3969 100644
--- a/src/lib/tiff_decoder.h
+++ b/src/lib/tiff_decoder.h
@@ -52,6 +52,7 @@ public:
int audio_channels () const;
int audio_sample_rate () const;
AVSampleFormat audio_sample_format () const;
+ int64_t audio_channel_layout () const;
private:
bool do_pass ();
diff --git a/src/lib/util.cc b/src/lib/util.cc
index 450ba5b8e..9896bff60 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -509,3 +509,13 @@ md5_digest (string file)
return s.str ();
}
+
+int
+dcp_audio_sample_rate (int fs)
+{
+ if (fs <= 48000) {
+ return 48000;
+ }
+
+ return 96000;
+}
diff --git a/src/lib/util.h b/src/lib/util.h
index 1f635677a..b3c1ebc05 100644
--- a/src/lib/util.h
+++ b/src/lib/util.h
@@ -119,4 +119,6 @@ struct Position
extern std::string crop_string (Position, Size);
+extern int dcp_audio_sample_rate (int);
+
#endif