From 4928ece9b10df775ab3003c024f52bdd30d8f591 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 26 Jul 2012 22:17:58 +0100 Subject: [PATCH] Implemented but faulty. --- src/lib/decoder.cc | 86 ++++++++++++++++++++++++++++++++--- src/lib/decoder.h | 9 ++++ src/lib/ffmpeg_decoder.cc | 6 +++ src/lib/ffmpeg_decoder.h | 1 + src/lib/film_state.h | 2 +- src/lib/imagemagick_decoder.h | 4 ++ src/lib/j2k_wav_encoder.cc | 2 +- src/lib/tiff_decoder.cc | 8 +++- src/lib/tiff_decoder.h | 1 + src/lib/util.cc | 10 ++++ src/lib/util.h | 2 + src/tools/wscript | 1 - wscript | 1 + 13 files changed, 122 insertions(+), 11 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 } +#include #include "film.h" #include "format.h" #include "job.h" @@ -67,6 +68,7 @@ Decoder::Decoder (boost::shared_ptr s, boost::shared_ptraudio_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 #include #include +extern "C" { +#include +} #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 s, shared_ptraudio_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 diff --git a/src/tools/wscript b/src/tools/wscript index 4c4979190..3be2d0eba 100644 --- a/src/tools/wscript +++ b/src/tools/wscript @@ -14,7 +14,6 @@ def build(bld): p.append('playomatic') for t in p: obj = bld(features = 'cxx cxxprogram') - obj.uselib = 'BOOST_THREAD WXWIDGETS' obj.includes = ['..'] obj.use = ['libdvdomatic', 'libdvdomatic-wx'] obj.source = '%s.cc' % t diff --git a/wscript b/wscript index 617875a70..8a7b2f527 100644 --- a/wscript +++ b/wscript @@ -58,6 +58,7 @@ def configure(conf): conf.check_cfg(package = 'libavcodec', args = '--cflags --libs', uselib_store = 'AVCODEC', mandatory = True) conf.check_cfg(package = 'libavutil', args = '--cflags --libs', uselib_store = 'AVUTIL', mandatory = True) conf.check_cfg(package = 'libswscale', args = '--cflags --libs', uselib_store = 'SWSCALE', mandatory = True) + conf.check_cfg(package = 'libswresample', args = '--cflags --libs', uselib_store = 'SWRESAMPLE', mandatory = True) conf.check_cfg(package = 'libpostproc', args = '--cflags --libs', uselib_store = 'POSTPROC', mandatory = True) conf.check_cfg(package = 'sndfile', args = '--cflags --libs', uselib_store = 'SNDFILE', mandatory = True) conf.check_cfg(package = 'libdcp', args = '--cflags --libs', uselib_store = 'DCP', mandatory = True) -- 2.30.2