More various AudioStream hacks.
authorCarl Hetherington <cth@carlh.net>
Sat, 10 Nov 2012 13:19:09 +0000 (13:19 +0000)
committerCarl Hetherington <cth@carlh.net>
Sat, 10 Nov 2012 13:19:09 +0000 (13:19 +0000)
20 files changed:
src/lib/ab_transcoder.cc
src/lib/decoder.cc
src/lib/decoder.h
src/lib/encoder.h
src/lib/examine_content_job.cc
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/film.cc
src/lib/film.h
src/lib/imagemagick_encoder.h
src/lib/j2k_still_encoder.h
src/lib/j2k_wav_encoder.cc
src/lib/j2k_wav_encoder.h
src/lib/stream.cc
src/lib/stream.h
src/lib/transcoder.cc
src/wx/film_editor.cc
src/wx/wx_util.cc
src/wx/wx_util.h
test/test.cc

index c40c0916e6f1ee474ca3b3ea2b35152fee827d7a..4183749c83bd3dec4b26463d503ecf225221ee76 100644 (file)
@@ -100,7 +100,7 @@ ABTranscoder::process_video (shared_ptr<Image> yuv, SourceFrame frame, shared_pt
 void
 ABTranscoder::go ()
 {
-       _encoder->process_begin (_da->audio_channel_layout());
+       _encoder->process_begin ();
        _da->process_begin ();
        _db->process_begin ();
        
index 01c4edf604b9864e3f011d7a45afee81ffd47217..2f66aff68b4fb63fc5c5804472fe76eb9c41169d 100644 (file)
@@ -43,6 +43,7 @@ using std::min;
 using std::pair;
 using std::list;
 using boost::shared_ptr;
+using boost::optional;
 
 /** @param f Film.
  *  @param o Options.
@@ -73,31 +74,33 @@ Decoder::~Decoder ()
 void
 Decoder::process_begin ()
 {
-       _delay_in_frames = _film->audio_delay() * audio_sample_rate() / 1000;
-       _delay_line = new DelayLine (audio_channels(), _delay_in_frames);
+       if (_audio_stream) {
+               _delay_in_frames = _film->audio_delay() * _audio_stream.get().sample_rate() / 1000;
+               _delay_line = new DelayLine (_audio_stream.get().channels(), _delay_in_frames);
+       }
 }
 
 /** Finish off a decode processing run */
 void
 Decoder::process_end ()
 {
-       if (_delay_in_frames < 0 && _opt->decode_audio && audio_channels()) {
-               shared_ptr<AudioBuffers> b (new AudioBuffers (audio_channels(), -_delay_in_frames));
+       if (_delay_in_frames < 0 && _opt->decode_audio && _audio_stream) {
+               shared_ptr<AudioBuffers> b (new AudioBuffers (_audio_stream.get().channels(), -_delay_in_frames));
                b->make_silent ();
                emit_audio (b);
        }
 
-       if (_opt->decode_audio && audio_channels()) {
+       if (_opt->decode_audio && _audio_stream) {
 
                /* Ensure that our video and audio emissions are the same length */
 
-               int64_t audio_short_by_frames = video_frames_to_audio_frames (_video_frame, audio_sample_rate(), frames_per_second()) - _audio_frame;
+               int64_t audio_short_by_frames = video_frames_to_audio_frames (_video_frame, _audio_stream.get().sample_rate(), frames_per_second()) - _audio_frame;
 
                _film->log()->log (
                        String::compose (
                                "Decoder has emitted %1 video frames (which equals %2 audio frames) and %3 audio frames",
                                _video_frame,
-                               video_frames_to_audio_frames (_video_frame, audio_sample_rate(), frames_per_second()),
+                               video_frames_to_audio_frames (_video_frame, _audio_stream.get().sample_rate(), frames_per_second()),
                                _audio_frame
                                )
                        );
@@ -107,7 +110,7 @@ Decoder::process_end ()
                        _film->log()->log (String::compose ("Emitted %1 too many audio frames", -audio_short_by_frames));
                        
                        /* We have emitted more audio than video.  Emit enough black video frames so that we reverse this */
-                       int const black_video_frames = ceil (-audio_short_by_frames * frames_per_second() / audio_sample_rate());
+                       int const black_video_frames = ceil (-audio_short_by_frames * frames_per_second() / _audio_stream.get().sample_rate());
 
                        _film->log()->log (String::compose ("Emitting %1 frames of black video", black_video_frames));
 
@@ -118,12 +121,12 @@ Decoder::process_end ()
                        }
 
                        /* Now recompute our check value */
-                       audio_short_by_frames = video_frames_to_audio_frames (_video_frame, audio_sample_rate(), frames_per_second()) - _audio_frame;
+                       audio_short_by_frames = video_frames_to_audio_frames (_video_frame, _audio_stream.get().sample_rate(), frames_per_second()) - _audio_frame;
                }
        
                if (audio_short_by_frames > 0) {
                        _film->log()->log (String::compose ("Emitted %1 too few audio frames", audio_short_by_frames));
-                       shared_ptr<AudioBuffers> b (new AudioBuffers (audio_channels(), audio_short_by_frames));
+                       shared_ptr<AudioBuffers> b (new AudioBuffers (_audio_stream.get().channels(), audio_short_by_frames));
                        b->make_silent ();
                        emit_audio (b);
                }
@@ -243,3 +246,15 @@ Decoder::process_subtitle (shared_ptr<TimedSubtitle> s)
                _timed_subtitle->subtitle()->set_position (Position (p.x - _film->crop().left, p.y - _film->crop().top));
        }
 }
+
+void
+Decoder::set_audio_stream (optional<AudioStream> s)
+{
+       _audio_stream = s;
+}
+
+void
+Decoder::set_subtitle_stream (optional<SubtitleStream> s)
+{
+       _subtitle_stream = s;
+}
index 1807254dbc1c57a35154ad3a136b72bcd0ff4398..d0e20b03af5de124a9d5057c267b1f35849e5e98 100644 (file)
@@ -61,12 +61,6 @@ public:
        virtual float frames_per_second () const = 0;
        /** @return native size in pixels */
        virtual Size native_size () const = 0;
-       /** @return number of audio channels */
-       virtual int audio_channels () const = 0;
-       /** @return audio sampling rate in Hz */
-       virtual int audio_sample_rate () const = 0;
-       virtual int64_t audio_channel_layout () const = 0;
-       virtual bool has_subtitles () const = 0;
 
        virtual int time_base_numerator () const = 0;
        virtual int time_base_denominator () const = 0;
@@ -82,12 +76,23 @@ public:
                return _video_frame;
        }
 
-       virtual std::vector<AudioStream> audio_streams () const {
-               return std::vector<AudioStream> ();
+       virtual void set_audio_stream (boost::optional<AudioStream>);
+       virtual void set_subtitle_stream (boost::optional<SubtitleStream>);
+
+       boost::optional<AudioStream> audio_stream () const {
+               return _audio_stream;
+       }
+
+       boost::optional<SubtitleStream> subtitle_stream () const {
+               return _subtitle_stream;
+       }
+
+       std::vector<AudioStream> audio_streams () const {
+               return _audio_streams;
        }
        
-       virtual std::vector<SubtitleStream> subtitle_streams () const {
-               return std::vector<SubtitleStream> ();
+       std::vector<SubtitleStream> subtitle_streams () const {
+               return _subtitle_streams;
        }
 
        /** Emitted when a video frame is ready.
@@ -116,13 +121,19 @@ protected:
        /** associated Job, or 0 */
        Job* _job;
 
+       boost::optional<AudioStream> _audio_stream;
+       boost::optional<SubtitleStream> _subtitle_stream;
+
+       std::vector<AudioStream> _audio_streams;
+       std::vector<SubtitleStream> _subtitle_streams;
+       
 private:
        void emit_video (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>);
        void emit_audio (boost::shared_ptr<AudioBuffers>);
 
        SourceFrame _video_frame;
        int64_t _audio_frame;
-       
+
        std::list<boost::shared_ptr<FilterGraph> > _filter_graphs;
 
        DelayLine* _delay_line;
index 2d9780b52e07cc61ec57bcb95ea73f4265fa9da9..e04397f78b7911638be43fa5d87dff2e0900b58d 100644 (file)
@@ -55,7 +55,7 @@ public:
        Encoder (boost::shared_ptr<const Film> f, boost::shared_ptr<const Options> o);
 
        /** Called to indicate that a processing run is about to begin */
-       virtual void process_begin (int64_t audio_channel_layout) = 0;
+       virtual void process_begin () {}
 
        /** Call with a frame of video.
         *  @param i Video frame image.
@@ -68,7 +68,7 @@ public:
        void process_audio (boost::shared_ptr<const AudioBuffers>, int64_t);
 
        /** Called when a processing run has finished */
-       virtual void process_end () = 0;
+       virtual void process_end () {}
 
        float current_frames_per_second () const;
        bool skipping () const;
index 4646fe8fcdece4092fec59897d0112cef72243c3..b13e9d9d59a901f83d5c2b0c22973117af85fb15 100644 (file)
@@ -59,10 +59,16 @@ void
 ExamineContentJob::run ()
 {
        /* Decode the content to get an accurate length */
+
+       /* We don't want to use any existing length here, as progress
+          will be messed up.
+       */
+       _film->unset_length ();
        
        shared_ptr<Options> o (new Options ("", "", ""));
        o->out_size = Size (512, 512);
        o->apply_crop = false;
+       o->decode_audio = false;
 
        descend (0.5);
 
index 9d396f423dbfcd5c06b78d7621f6a25ba69e1816..1cac25ca15e0fcfc5ce5b75823bf4fd4620fca5c 100644 (file)
@@ -54,13 +54,12 @@ using std::string;
 using std::vector;
 using std::stringstream;
 using boost::shared_ptr;
+using boost::optional;
 
 FFmpegDecoder::FFmpegDecoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j)
        : Decoder (f, o, j)
        , _format_context (0)
        , _video_stream (-1)
-       , _audio_stream (-1)
-       , _subtitle_stream (-1)
        , _frame (0)
        , _video_codec_context (0)
        , _video_codec (0)
@@ -116,28 +115,12 @@ FFmpegDecoder::setup_general ()
                if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
                        _video_stream = i;
                } else if (s->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-                       if (_audio_stream == -1) {
-                               _audio_stream = i;
-                       }
-                       _audio_streams.push_back (AudioStream (stream_name (s), i, s->codec->channels));
+                       _audio_streams.push_back (AudioStream (stream_name (s), i, s->codec->sample_rate, s->codec->channel_layout));
                } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
-                       if (_subtitle_stream == -1) {
-                               _subtitle_stream = i;
-                       }
                        _subtitle_streams.push_back (SubtitleStream (stream_name (s), i));
                }
        }
 
-       /* Now override audio and subtitle streams with those from the Film, if it has any */
-
-       if (_film->audio_stream_index() != -1) {
-               _audio_stream = _film->audio_stream().id();
-       }
-
-       if (_film->subtitle_stream_index() != -1) {
-               _subtitle_stream = _film->subtitle_stream().id ();
-       }
-
        if (_video_stream < 0) {
                throw DecodeError ("could not find video stream");
        }
@@ -173,11 +156,11 @@ FFmpegDecoder::setup_video ()
 void
 FFmpegDecoder::setup_audio ()
 {
-       if (_audio_stream < 0) {
+       if (!_audio_stream) {
                return;
        }
        
-       _audio_codec_context = _format_context->streams[_audio_stream]->codec;
+       _audio_codec_context = _format_context->streams[_audio_stream.get().id()]->codec;
        _audio_codec = avcodec_find_decoder (_audio_codec_context->codec_id);
 
        if (_audio_codec == 0) {
@@ -193,18 +176,18 @@ FFmpegDecoder::setup_audio ()
        */
 
        if (_audio_codec_context->channel_layout == 0) {
-               _audio_codec_context->channel_layout = av_get_default_channel_layout (audio_channels ());
+               _audio_codec_context->channel_layout = av_get_default_channel_layout (_audio_stream.get().channels());
        }
 }
 
 void
 FFmpegDecoder::setup_subtitle ()
 {
-       if (_subtitle_stream < 0) {
+       if (!_subtitle_stream) {
                return;
        }
 
-       _subtitle_codec_context = _format_context->streams[_subtitle_stream]->codec;
+       _subtitle_codec_context = _format_context->streams[_subtitle_stream.get().id()]->codec;
        _subtitle_codec = avcodec_find_decoder (_subtitle_codec_context->codec_id);
 
        if (_subtitle_codec == 0) {
@@ -243,7 +226,7 @@ FFmpegDecoder::pass ()
                        process_video (_frame);
                }
 
-               if (_audio_stream >= 0 && _opt->decode_audio && _film->use_source_audio()) {
+               if (_audio_stream && _opt->decode_audio && _film->use_source_audio()) {
                        while (avcodec_decode_audio4 (_audio_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
                                int const data_size = av_samples_get_buffer_size (
                                        0, _audio_codec_context->channels, _frame->nb_samples, audio_sample_format (), 1
@@ -307,7 +290,7 @@ FFmpegDecoder::pass ()
                        }
                }
 
-       } else if (_audio_stream >= 0 && _packet.stream_index == _audio_stream && _opt->decode_audio && _film->use_source_audio()) {
+       } else if (_audio_stream && _packet.stream_index == _audio_stream.get().id() && _opt->decode_audio && _film->use_source_audio()) {
 
                int frame_finished;
                if (avcodec_decode_audio4 (_audio_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
@@ -331,17 +314,17 @@ FFmpegDecoder::pass ()
                                        */
                        
                                        /* frames of silence that we must push */
-                                       int const s = rint ((_first_audio.get() - _first_video.get()) * audio_sample_rate ());
+                                       int const s = rint ((_first_audio.get() - _first_video.get()) * _audio_stream.get().sample_rate ());
                                        
                                        _film->log()->log (
                                                String::compose (
                                                        "First video at %1, first audio at %2, pushing %3 frames of silence for %4 channels (%5 bytes per sample)",
-                                                       _first_video.get(), _first_audio.get(), s, audio_channels(), bytes_per_audio_sample()
+                                                       _first_video.get(), _first_audio.get(), s, _audio_stream.get().channels(), bytes_per_audio_sample()
                                                        )
                                                );
                                        
                                        if (s) {
-                                               shared_ptr<AudioBuffers> audio (new AudioBuffers (audio_channels(), s));
+                                               shared_ptr<AudioBuffers> audio (new AudioBuffers (_audio_stream.get().channels(), s));
                                                audio->make_silent ();
                                                process_audio (audio);
                                        }
@@ -356,7 +339,7 @@ FFmpegDecoder::pass ()
                        }
                }
                        
-       } else if (_subtitle_stream >= 0 && _packet.stream_index == _subtitle_stream && _opt->decode_subtitles && _first_video) {
+       } else if (_subtitle_stream && _packet.stream_index == _subtitle_stream.get().id() && _opt->decode_subtitles && _first_video) {
 
                int got_subtitle;
                AVSubtitle sub;
@@ -385,11 +368,11 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
        
        /* Deinterleave and convert to float */
 
-       assert ((size % (bytes_per_audio_sample() * audio_channels())) == 0);
+       assert ((size % (bytes_per_audio_sample() * _audio_stream.get().channels())) == 0);
 
        int const total_samples = size / bytes_per_audio_sample();
        int const frames = total_samples / _film->audio_channels();
-       shared_ptr<AudioBuffers> audio (new AudioBuffers (audio_channels(), frames));
+       shared_ptr<AudioBuffers> audio (new AudioBuffers (_audio_stream.get().channels(), frames));
 
        switch (audio_sample_format()) {
        case AV_SAMPLE_FMT_S16:
@@ -454,26 +437,6 @@ FFmpegDecoder::frames_per_second () const
        return av_q2d (s->r_frame_rate);
 }
 
-int
-FFmpegDecoder::audio_channels () const
-{
-       if (_audio_codec_context == 0) {
-               return 0;
-       }
-
-       return _audio_codec_context->channels;
-}
-
-int
-FFmpegDecoder::audio_sample_rate () const
-{
-       if (_audio_codec_context == 0) {
-               return 0;
-       }
-       
-       return _audio_codec_context->sample_rate;
-}
-
 AVSampleFormat
 FFmpegDecoder::audio_sample_format () const
 {
@@ -484,16 +447,6 @@ FFmpegDecoder::audio_sample_format () const
        return _audio_codec_context->sample_fmt;
 }
 
-int64_t
-FFmpegDecoder::audio_channel_layout () const
-{
-       if (_audio_codec_context == 0) {
-               return 0;
-       }
-       
-       return _audio_codec_context->channel_layout;
-}
-
 Size
 FFmpegDecoder::native_size () const
 {
@@ -530,24 +483,6 @@ FFmpegDecoder::sample_aspect_ratio_denominator () const
        return _video_codec_context->sample_aspect_ratio.den;
 }
 
-bool
-FFmpegDecoder::has_subtitles () const
-{
-       return (_subtitle_stream != -1);
-}
-
-vector<AudioStream>
-FFmpegDecoder::audio_streams () const
-{
-       return _audio_streams;
-}
-
-vector<SubtitleStream>
-FFmpegDecoder::subtitle_streams () const
-{
-       return _subtitle_streams;
-}
-
 string
 FFmpegDecoder::stream_name (AVStream* s) const
 {
@@ -578,3 +513,17 @@ FFmpegDecoder::bytes_per_audio_sample () const
 {
        return av_get_bytes_per_sample (audio_sample_format ());
 }
+
+void
+FFmpegDecoder::set_audio_stream (optional<AudioStream> s)
+{
+       Decoder::set_audio_stream (s);
+       setup_audio ();
+}
+
+void
+FFmpegDecoder::set_subtitle_stream (optional<SubtitleStream> s)
+{
+       Decoder::set_subtitle_stream (s);
+       setup_subtitle ();
+}
index 8373125cd5a2b93ad5824dc4950d90bf27d27303..856ac0801fcbffc4067c596f4e1ee6f855ddee67 100644 (file)
@@ -58,13 +58,9 @@ public:
        /* Methods to query our input video */
        float frames_per_second () const;
        Size native_size () const;
-       int audio_channels () const;
-       int audio_sample_rate () const;
-       int64_t audio_channel_layout () const;
-       bool has_subtitles () const;
 
-       std::vector<AudioStream> audio_streams () const;
-       std::vector<SubtitleStream> subtitle_streams () const;
+       void set_audio_stream (boost::optional<AudioStream>);
+       void set_subtitle_stream (boost::optional<SubtitleStream>);
 
 private:
 
@@ -89,14 +85,9 @@ private:
 
        AVFormatContext* _format_context;
        int _video_stream;
-       int _audio_stream; ///< may be < 0 if there is no audio
-       int _subtitle_stream; ///< may be < 0 if there is no subtitle
        
        AVFrame* _frame;
 
-       std::vector<AudioStream> _audio_streams;
-       std::vector<SubtitleStream> _subtitle_streams;
-       
        AVCodecContext* _video_codec_context;
        AVCodec* _video_codec;
        AVCodecContext* _audio_codec_context;    ///< may be 0 if there is no audio
index cc5de0e7985f09bdaf8c6f0fca7c32a1a1ecdfcf..3ce3a8df34519b70c929e1253ff87f19c9011a68 100644 (file)
@@ -69,6 +69,7 @@ using boost::lexical_cast;
 using boost::to_upper_copy;
 using boost::ends_with;
 using boost::starts_with;
+using boost::optional;
 
 /** Construct a Film object in a given directory, reading any metadata
  *  file that exists in that directory.  An exception will be thrown if
@@ -87,16 +88,12 @@ Film::Film (string d, bool must_exist)
        , _dcp_trim_end (0)
        , _dcp_ab (false)
        , _use_source_audio (true)
-       , _audio_stream (-1)
        , _audio_gain (0)
        , _audio_delay (0)
        , _still_duration (10)
-       , _subtitle_stream (-1)
        , _with_subtitles (false)
        , _subtitle_offset (0)
        , _subtitle_scale (1)
-       , _audio_sample_rate (0)
-       , _has_subtitles (false)
        , _frames_per_second (0)
        , _dirty (false)
 {
@@ -168,9 +165,7 @@ Film::Film (Film const & o)
        , _thumbs            (o._thumbs)
        , _size              (o._size)
        , _length            (o._length)
-       , _audio_sample_rate (o._audio_sample_rate)
        , _content_digest    (o._content_digest)
-       , _has_subtitles     (o._has_subtitles)
        , _audio_streams     (o._audio_streams)
        , _subtitle_streams  (o._subtitle_streams)
        , _frames_per_second (o._frames_per_second)
@@ -263,10 +258,12 @@ Film::make_dcp (bool transcode)
        o->ratio = format()->ratio_as_float (shared_from_this ());
        if (dcp_length ()) {
                o->video_decode_range = make_pair (dcp_trim_start(), dcp_trim_start() + dcp_length().get());
-               o->audio_decode_range = make_pair (
-                       video_frames_to_audio_frames (o->video_decode_range.get().first, audio_sample_rate(), frames_per_second()),
-                       video_frames_to_audio_frames (o->video_decode_range.get().second, audio_sample_rate(), frames_per_second())
-                       );
+               if (audio_stream()) {
+                       o->audio_decode_range = make_pair (
+                               video_frames_to_audio_frames (o->video_decode_range.get().first, audio_stream().get().sample_rate(), frames_per_second()),
+                               video_frames_to_audio_frames (o->video_decode_range.get().second, audio_stream().get().sample_rate(), frames_per_second())
+                               );
+               }
                        
        }
        o->decode_subtitles = with_subtitles ();
@@ -422,14 +419,18 @@ Film::write_metadata () const
        f << "dcp_trim_end " << _dcp_trim_end << "\n";
        f << "dcp_ab " << (_dcp_ab ? "1" : "0") << "\n";
        f << "use_source_audio " << (_use_source_audio ? "1" : "0") << "\n";
-       f << "selected_audio_stream " << _audio_stream << "\n";
+       if (_audio_stream) {
+               f << "selected_audio_stream " << _audio_stream.get().to_string() << "\n";
+       }
        for (vector<string>::const_iterator i = _external_audio.begin(); i != _external_audio.end(); ++i) {
                f << "external_audio " << *i << "\n";
        }
        f << "audio_gain " << _audio_gain << "\n";
        f << "audio_delay " << _audio_delay << "\n";
        f << "still_duration " << _still_duration << "\n";
-       f << "selected_subtitle_stream " << _subtitle_stream << "\n";
+       if (_subtitle_stream) {
+               f << "selected_subtitle_stream " << _subtitle_stream.get().to_string() << "\n";
+       }
        f << "with_subtitles " << _with_subtitles << "\n";
        f << "subtitle_offset " << _subtitle_offset << "\n";
        f << "subtitle_scale " << _subtitle_scale << "\n";
@@ -450,9 +451,7 @@ Film::write_metadata () const
        f << "width " << _size.width << "\n";
        f << "height " << _size.height << "\n";
        f << "length " << _length.get_value_or(0) << "\n";
-       f << "audio_sample_rate " << _audio_sample_rate << "\n";
        f << "content_digest " << _content_digest << "\n";
-       f << "has_subtitles " << _has_subtitles << "\n";
 
        for (vector<AudioStream>::const_iterator i = _audio_streams.begin(); i != _audio_streams.end(); ++i) {
                f << "audio_stream " << i->to_string () << "\n";
@@ -516,7 +515,7 @@ Film::read_metadata ()
                } else if (k == "use_source_audio") {
                        _use_source_audio = (v == "1");
                } else if (k == "selected_audio_stream") {
-                       _audio_stream = atoi (v.c_str ());
+                       _audio_stream = AudioStream (v);
                } else if (k == "external_audio") {
                        _external_audio.push_back (v);
                } else if (k == "audio_gain") {
@@ -526,7 +525,7 @@ Film::read_metadata ()
                } else if (k == "still_duration") {
                        _still_duration = atoi (v.c_str ());
                } else if (k == "selected_subtitle_stream") {
-                       _subtitle_stream = atoi (v.c_str ());
+                       _subtitle_stream = SubtitleStream (v);
                } else if (k == "with_subtitles") {
                        _with_subtitles = (v == "1");
                } else if (k == "subtitle_offset") {
@@ -565,12 +564,8 @@ Film::read_metadata ()
                        if (vv) {
                                _length = vv;
                        }
-               } else if (k == "audio_sample_rate") {
-                       _audio_sample_rate = atoi (v.c_str ());
                } else if (k == "content_digest") {
                        _content_digest = v;
-               } else if (k == "has_subtitles") {
-                       _has_subtitles = (v == "1");
                } else if (k == "audio_stream") {
                        _audio_streams.push_back (AudioStream (v));
                } else if (k == "subtitle_stream") {
@@ -711,7 +706,7 @@ int
 Film::target_audio_sample_rate () const
 {
        /* Resample to a DCI-approved sample rate */
-       double t = dcp_audio_sample_rate (audio_sample_rate());
+       double t = dcp_audio_sample_rate (audio_stream().get().sample_rate());
 
        DCPFrameRate dfr = dcp_frame_rate (frames_per_second ());
 
@@ -892,6 +887,9 @@ Film::set_content (string c)
                _content = c;
        }
 
+       _audio_stream = optional<AudioStream> ();
+       _subtitle_stream = optional<SubtitleStream> ();
+
        /* Create a temporary decoder so that we can get information
           about the content.
        */
@@ -904,12 +902,17 @@ Film::set_content (string c)
                
                set_size (d->native_size ());
                set_frames_per_second (d->frames_per_second ());
-               set_audio_sample_rate (d->audio_sample_rate ());
-               set_has_subtitles (d->has_subtitles ());
                set_audio_streams (d->audio_streams ());
                set_subtitle_streams (d->subtitle_streams ());
-               set_audio_stream (audio_streams().empty() ? -1 : 0);
-               set_subtitle_stream (subtitle_streams().empty() ? -1 : 0);
+
+               /* Start off with the first audio and subtitle streams */
+               if (!d->audio_streams().empty()) {
+                       set_audio_stream (d->audio_streams().front());
+               }
+               
+               if (!d->subtitle_streams().empty()) {
+                       set_subtitle_stream (d->subtitle_streams().front());
+               }
                
                {
                        boost::mutex::scoped_lock lm (_state_mutex);
@@ -1079,7 +1082,7 @@ Film::set_use_source_audio (bool s)
 }
 
 void
-Film::set_audio_stream (int s)
+Film::set_audio_stream (optional<AudioStream> s)
 {
        {
                boost::mutex::scoped_lock lm (_state_mutex);
@@ -1129,7 +1132,7 @@ Film::set_still_duration (int d)
 }
 
 void
-Film::set_subtitle_stream (int s)
+Film::set_subtitle_stream (optional<SubtitleStream> s)
 {
        {
                boost::mutex::scoped_lock lm (_state_mutex);
@@ -1278,16 +1281,6 @@ Film::unset_length ()
        signal_changed (LENGTH);
 }      
 
-void
-Film::set_audio_sample_rate (int r)
-{
-       {
-               boost::mutex::scoped_lock lm (_state_mutex);
-               _audio_sample_rate = r;
-       }
-       signal_changed (AUDIO_SAMPLE_RATE);
-}
-
 void
 Film::set_content_digest (string d)
 {
@@ -1298,16 +1291,6 @@ Film::set_content_digest (string d)
        _dirty = true;
 }
 
-void
-Film::set_has_subtitles (bool s)
-{
-       {
-               boost::mutex::scoped_lock lm (_state_mutex);
-               _has_subtitles = s;
-       }
-       signal_changed (HAS_SUBTITLES);
-}
-
 void
 Film::set_audio_streams (vector<AudioStream> s)
 {
@@ -1357,8 +1340,8 @@ Film::audio_channels () const
        boost::mutex::scoped_lock lm (_state_mutex);
        
        if (_use_source_audio) {
-               if (_audio_stream >= 0) {
-                       return _audio_streams[_audio_stream].channels ();
+               if (_audio_stream) {
+                       return _audio_stream.get().channels ();
                }
        } else {
                int last_filled = -1;
index 168a5e0b207ce3f350549ba61e3bfb6b6fb89015..af1f49e2ef56534dc847123f7183ea3eb1694e3a 100644 (file)
@@ -134,8 +134,6 @@ public:
                THUMBS,
                SIZE,
                LENGTH,
-               AUDIO_SAMPLE_RATE,
-               HAS_SUBTITLES,
                AUDIO_STREAMS,
                SUBTITLE_STREAMS,
                FRAMES_PER_SECOND,
@@ -209,17 +207,11 @@ public:
                return _use_source_audio;
        }
 
-       int audio_stream_index () const {
+       boost::optional<AudioStream> audio_stream () const {
                boost::mutex::scoped_lock lm (_state_mutex);
                return _audio_stream;
        }
 
-       AudioStream audio_stream () const {
-               boost::mutex::scoped_lock lm (_state_mutex);
-               assert (_audio_stream < int (_audio_streams.size()));
-               return _audio_streams[_audio_stream];
-       }
-
        std::vector<std::string> external_audio () const {
                boost::mutex::scoped_lock lm (_state_mutex);
                return _external_audio;
@@ -240,17 +232,11 @@ public:
                return _still_duration;
        }
 
-       int subtitle_stream_index () const {
+       boost::optional<SubtitleStream> subtitle_stream () const {
                boost::mutex::scoped_lock lm (_state_mutex);
                return _subtitle_stream;
        }
 
-       SubtitleStream subtitle_stream () const {
-               boost::mutex::scoped_lock lm (_state_mutex);
-               assert (_subtitle_stream < int (_subtitle_streams.size()));
-               return _subtitle_streams[_subtitle_stream];
-       }
-
        bool with_subtitles () const {
                boost::mutex::scoped_lock lm (_state_mutex);
                return _with_subtitles;
@@ -316,21 +302,11 @@ public:
                return _length;
        }
        
-       int audio_sample_rate () const {
-               boost::mutex::scoped_lock lm (_state_mutex);
-               return _audio_sample_rate;
-       }
-       
        std::string content_digest () const {
                boost::mutex::scoped_lock lm (_state_mutex);
                return _content_digest;
        }
        
-       bool has_subtitles () const {
-               boost::mutex::scoped_lock lm (_state_mutex);
-               return _has_subtitles;
-       }
-
        std::vector<AudioStream> audio_streams () const {
                boost::mutex::scoped_lock lm (_state_mutex);
                return _audio_streams;
@@ -366,12 +342,12 @@ public:
        void set_dcp_trim_end (int);
        void set_dcp_ab (bool);
        void set_use_source_audio (bool);
-       void set_audio_stream (int);
+       void set_audio_stream (boost::optional<AudioStream>);
        void set_external_audio (std::vector<std::string>);
        void set_audio_gain (float);
        void set_audio_delay (int);
        void set_still_duration (int);
-       void set_subtitle_stream (int);
+       void set_subtitle_stream (boost::optional<SubtitleStream>);
        void set_with_subtitles (bool);
        void set_subtitle_offset (int);
        void set_subtitle_scale (float);
@@ -386,9 +362,7 @@ public:
        void set_size (Size);
        void set_length (SourceFrame);
        void unset_length ();
-       void set_audio_sample_rate (int);
        void set_content_digest (std::string);
-       void set_has_subtitles (bool);
        void set_audio_streams (std::vector<AudioStream>);
        void set_subtitle_streams (std::vector<SubtitleStream>);
        void set_frames_per_second (float);
@@ -447,8 +421,7 @@ private:
        */
        bool _dcp_ab;
        bool _use_source_audio;
-       /** An index into our _audio_streams vector for the stream to use for audio, or -1 if there is none */
-       int _audio_stream;
+       boost::optional<AudioStream> _audio_stream;
        std::vector<std::string> _external_audio;
        /** Gain to apply to audio in dB */
        float _audio_gain;
@@ -456,8 +429,7 @@ private:
        int _audio_delay;
        /** Duration to make still-sourced films (in seconds) */
        int _still_duration;
-       /** An index into our _subtitle_streams vector for the stream to use for subtitles, or -1 if there is none */
-       int _subtitle_stream;
+       boost::optional<SubtitleStream> _subtitle_stream;
        /** True if subtitles should be shown for this film */
        bool _with_subtitles;
        /** y offset for placing subtitles, in source pixels; +ve is further down
@@ -484,12 +456,8 @@ private:
        Size _size;
        /** Actual length of the source (in video frames) from examining it */
        boost::optional<SourceFrame> _length;
-       /** Sample rate of the source audio, in Hz */
-       int _audio_sample_rate;
        /** MD5 digest of our content file */
        std::string _content_digest;
-       /** true if the source has subtitles */
-       bool _has_subtitles;
        /** the audio streams that the source has */
        std::vector<AudioStream> _audio_streams;
        /** the subtitle streams that the source has */
index 9adfbf56bf8965e0fc0ec3a3a431ac8b63ae6735..02458fc5b08b32db129bf9747e5c429641e4a61b 100644 (file)
@@ -36,9 +36,6 @@ class ImageMagickEncoder : public Encoder
 public:
        ImageMagickEncoder (boost::shared_ptr<const Film> f, boost::shared_ptr<const Options> o);
 
-       void process_begin (int64_t audio_channel_layout) {}
-       void process_end () {}
-
 private:       
        void do_process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
        void do_process_audio (boost::shared_ptr<const AudioBuffers>) {}
index bc324e967b0ca7e48dd754ab5521c9194d0e1ea2..65cfa7cac0a918775611828a102752c4a0b1daff 100644 (file)
@@ -36,9 +36,6 @@ class J2KStillEncoder : public Encoder
 public:
        J2KStillEncoder (boost::shared_ptr<const Film>, boost::shared_ptr<const Options>);
 
-       void process_begin (int64_t audio_channel_layout) {}
-       void process_end () {}
-
 private:
        void do_process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
        void do_process_audio (boost::shared_ptr<const AudioBuffers>) {}
index 6d777babb22c2f7aac216b5a1d440ef3c2f02f53..108320d327059edcf4306b9e17ee2e1f75a88d82 100644 (file)
@@ -58,20 +58,22 @@ J2KWAVEncoder::J2KWAVEncoder (shared_ptr<const Film> f, shared_ptr<const Options
        , _audio_frames_written (0)
        , _process_end (false)
 {
-       /* Create sound output files with .tmp suffixes; we will rename
-          them if and when we complete.
-       */
-       for (int i = 0; i < _film->audio_channels(); ++i) {
-               SF_INFO sf_info;
-               sf_info.samplerate = dcp_audio_sample_rate (_film->audio_sample_rate());
-               /* We write mono files */
-               sf_info.channels = 1;
-               sf_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
-               SNDFILE* f = sf_open (_opt->multichannel_audio_out_path (i, true).c_str (), SFM_WRITE, &sf_info);
-               if (f == 0) {
-                       throw CreateFileError (_opt->multichannel_audio_out_path (i, true));
+       if (_film->audio_stream()) {
+               /* Create sound output files with .tmp suffixes; we will rename
+                  them if and when we complete.
+               */
+               for (int i = 0; i < _film->audio_channels(); ++i) {
+                       SF_INFO sf_info;
+                       sf_info.samplerate = dcp_audio_sample_rate (_film->audio_stream().get().sample_rate());
+                       /* We write mono files */
+                       sf_info.channels = 1;
+                       sf_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
+                       SNDFILE* f = sf_open (_opt->multichannel_audio_out_path (i, true).c_str (), SFM_WRITE, &sf_info);
+                       if (f == 0) {
+                               throw CreateFileError (_opt->multichannel_audio_out_path (i, true));
+                       }
+                       _sound_files.push_back (f);
                }
-               _sound_files.push_back (f);
        }
 }
 
@@ -225,24 +227,24 @@ J2KWAVEncoder::encoder_thread (ServerDescription* server)
 }
 
 void
-J2KWAVEncoder::process_begin (int64_t audio_channel_layout)
+J2KWAVEncoder::process_begin ()
 {
-       if (_film->audio_sample_rate() != _film->target_audio_sample_rate()) {
+       if (_film->audio_stream() && _film->audio_stream().get().sample_rate() != _film->target_audio_sample_rate()) {
 #ifdef HAVE_SWRESAMPLE
 
                stringstream s;
-               s << "Will resample audio from " << _film->audio_sample_rate() << " to " << _film->target_audio_sample_rate();
+               s << "Will resample audio from " << _film->audio_stream().get().sample_rate() << " to " << _film->target_audio_sample_rate();
                _film->log()->log (s.str ());
 
                /* We will be using planar float data when we call the resampler */
                _swr_context = swr_alloc_set_opts (
                        0,
-                       audio_channel_layout,
+                       _film->audio_stream().get().channel_layout(),
                        AV_SAMPLE_FMT_FLTP,
                        _film->target_audio_sample_rate(),
-                       audio_channel_layout,
+                       _film->audio_stream().get().channel_layout(),
                        AV_SAMPLE_FMT_FLTP,
-                       _film->audio_sample_rate(),
+                       _film->audio_stream().get().sample_rate(),
                        0, 0
                        );
                
@@ -310,9 +312,9 @@ J2KWAVEncoder::process_end ()
        }
 
 #if HAVE_SWRESAMPLE    
-       if (_swr_context) {
+       if (_film->audio_stream() && _swr_context) {
 
-               shared_ptr<AudioBuffers> out (new AudioBuffers (_film->audio_channels(), 256));
+               shared_ptr<AudioBuffers> out (new AudioBuffers (_film->audio_stream().get().channels(), 256));
                        
                while (1) {
                        int const frames = swr_convert (_swr_context, (uint8_t **) out->data(), 256, 0, 0);
@@ -333,20 +335,22 @@ J2KWAVEncoder::process_end ()
        }
 #endif
 
-       int const dcp_sr = dcp_audio_sample_rate (_film->audio_sample_rate ());
-       int64_t const extra_audio_frames = dcp_sr - (_audio_frames_written % dcp_sr);
-       shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), extra_audio_frames));
-       silence->make_silent ();
-       write_audio (silence);
-       
-       close_sound_files ();
-
-       /* Rename .wav.tmp files to .wav */
-       for (int i = 0; i < _film->audio_channels(); ++i) {
-               if (boost::filesystem::exists (_opt->multichannel_audio_out_path (i, false))) {
-                       boost::filesystem::remove (_opt->multichannel_audio_out_path (i, false));
+       if (_film->audio_stream()) {
+               int const dcp_sr = dcp_audio_sample_rate (_film->audio_stream().get().sample_rate ());
+               int64_t const extra_audio_frames = dcp_sr - (_audio_frames_written % dcp_sr);
+               shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_stream().get().channels(), extra_audio_frames));
+               silence->make_silent ();
+               write_audio (silence);
+               
+               close_sound_files ();
+               
+               /* Rename .wav.tmp files to .wav */
+               for (int i = 0; i < _film->audio_channels(); ++i) {
+                       if (boost::filesystem::exists (_opt->multichannel_audio_out_path (i, false))) {
+                               boost::filesystem::remove (_opt->multichannel_audio_out_path (i, false));
+                       }
+                       boost::filesystem::rename (_opt->multichannel_audio_out_path (i, true), _opt->multichannel_audio_out_path (i, false));
                }
-               boost::filesystem::rename (_opt->multichannel_audio_out_path (i, true), _opt->multichannel_audio_out_path (i, false));
        }
 }
 
@@ -360,9 +364,9 @@ J2KWAVEncoder::do_process_audio (shared_ptr<const AudioBuffers> audio)
        if (_swr_context) {
 
                /* Compute the resampled frames count and add 32 for luck */
-               int const max_resampled_frames = ceil (audio->frames() * _film->target_audio_sample_rate() / _film->audio_sample_rate()) + 32;
+               int const max_resampled_frames = ceil (audio->frames() * _film->target_audio_sample_rate() / _film->audio_stream().get().sample_rate()) + 32;
 
-               resampled.reset (new AudioBuffers (_film->audio_channels(), max_resampled_frames));
+               resampled.reset (new AudioBuffers (_film->audio_stream().get().channels(), max_resampled_frames));
 
                /* Resample audio */
                int const resampled_frames = swr_convert (
index b494be8e58d382430823fa7ff08cd9df95a5e155..5cf508cffb526d63bc73f5c9d0f8e34134d039f0 100644 (file)
@@ -50,7 +50,7 @@ public:
        J2KWAVEncoder (boost::shared_ptr<const Film>, boost::shared_ptr<const Options>);
        ~J2KWAVEncoder ();
 
-       void process_begin (int64_t audio_channel_layout);
+       void process_begin ();
        void process_end ();
 
 private:
index d1c2b5a9e589790c4a5c5b8193a16cd5f98aa40b..9d10813f77a52f7aeea6085fa784d7479fbad0cf 100644 (file)
@@ -26,7 +26,7 @@ using namespace std;
 AudioStream::AudioStream (string t)
 {
        stringstream n (t);
-       n >> _id >> _channels;
+       n >> _id >> _sample_rate >> _channel_layout;
 
        for (int i = 0; i < 2; ++i) {
                size_t const s = t.find (' ');
@@ -41,7 +41,7 @@ AudioStream::AudioStream (string t)
 string
 AudioStream::to_string () const
 {
-       return String::compose ("%1 %2 %3", _id, _channels, _name);
+       return String::compose ("%1 %2 %3 %4", _id, _sample_rate, _channel_layout, _name);
 }
 
 SubtitleStream::SubtitleStream (string t)
index 2db63c6208e12c75d92360b1b1676a9637a282b6..d6c4ca38270ad22f2b7183fadc5619e13b671248 100644 (file)
 #ifndef DVDOMATIC_STREAM_H
 #define DVDOMATIC_STREAM_H
 
+#include <stdint.h>
+extern "C" {
+#include <libavutil/audioconvert.h>
+}
+
 class Stream
 {
 public:
@@ -52,19 +57,29 @@ struct AudioStream : public Stream
 public:
        AudioStream (std::string t);
        
-       AudioStream (std::string n, int i, int c)
-               : Stream (n, i)
-               , _channels (c)
+       AudioStream (std::string n, int id, int r, int64_t l)
+               : Stream (n, id)
+               , _sample_rate (r)
+               , _channel_layout (l)
        {}
 
        std::string to_string () const;
 
        int channels () const {
-               return _channels;
+               return av_get_channel_layout_nb_channels (_channel_layout);
+       }
+
+       int sample_rate () const {
+               return _sample_rate;
+       }
+
+       int64_t channel_layout () const {
+               return _channel_layout;
        }
 
 private:
-       int _channels;
+       int _sample_rate;
+       int64_t _channel_layout;
 };
 
 class SubtitleStream : public Stream
index 66d5606afd30525378e66ae94b5889d84e104316..ac908768e34a14d2c20eede1390756fd06a14438 100644 (file)
@@ -29,6 +29,7 @@
 #include "transcoder.h"
 #include "encoder.h"
 #include "decoder_factory.h"
+#include "film.h"
 
 using std::string;
 using boost::shared_ptr;
@@ -45,6 +46,10 @@ Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j,
        , _decoder (decoder_factory (f, o, j))
 {
        assert (_encoder);
+
+       /* Set up the decoder to use the film's set streams */
+       _decoder->set_audio_stream (f->audio_stream ());
+       _decoder->set_subtitle_stream (f->subtitle_stream ());
        
        _decoder->Video.connect (bind (&Encoder::process_video, e, _1, _2, _3));
        _decoder->Audio.connect (bind (&Encoder::process_audio, e, _1, _2));
@@ -56,7 +61,7 @@ Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j,
 void
 Transcoder::go ()
 {
-       _encoder->process_begin (_decoder->audio_channel_layout());
+       _encoder->process_begin ();
        try {
                _decoder->go ();
        } catch (...) {
index f2446c22afce7a479a2e73ac186823d229723af2..e49bf62720ab0e7f36445b6a2548b8e025d26e76 100644 (file)
@@ -46,6 +46,7 @@
 #include "scaler.h"
 
 using std::string;
+using std::cout;
 using std::stringstream;
 using std::pair;
 using std::fixed;
@@ -484,12 +485,9 @@ FilmEditor::film_changed (Film::Property p)
                setup_subtitle_control_sensitivity ();
                setup_streams ();
                break;
-       case Film::HAS_SUBTITLES:
-               setup_subtitle_control_sensitivity ();
-               setup_streams ();
-               break;
        case Film::AUDIO_STREAMS:
        case Film::SUBTITLE_STREAMS:
+               setup_subtitle_control_sensitivity ();
                setup_streams ();
                break;
        case Film::FORMAT:
@@ -531,9 +529,6 @@ FilmEditor::film_changed (Film::Property p)
                s << fixed << setprecision(2) << _film->frames_per_second();
                _frames_per_second->SetLabel (std_to_wx (s.str ()));
                break;
-       case Film::AUDIO_SAMPLE_RATE:
-               setup_audio_details ();
-               break;
        case Film::SIZE:
                if (_film->size().width == 0 && _film->size().height == 0) {
                        _original_size->SetLabel (wxT (""));
@@ -602,12 +597,16 @@ FilmEditor::film_changed (Film::Property p)
                _dcp_name->SetLabel (std_to_wx (_film->dcp_name ()));
                break;
        case Film::AUDIO_STREAM:
-               checked_set (_audio_stream, _film->audio_stream_index ());
+               if (_film->audio_stream()) {
+                       checked_set (_audio_stream, _film->audio_stream().get().to_string());
+               }
                _dcp_name->SetLabel (std_to_wx (_film->dcp_name ()));
                setup_audio_details ();
                break;
        case Film::SUBTITLE_STREAM:
-               checked_set (_subtitle_stream, _film->subtitle_stream_index ());
+               if (_film->subtitle_stream()) {
+                       checked_set (_subtitle_stream, _film->subtitle_stream().get().to_string());
+               }
                break;
        case Film::USE_SOURCE_AUDIO:
                checked_set (_use_source_audio, _film->use_source_audio ());
@@ -687,13 +686,11 @@ FilmEditor::set_film (shared_ptr<Film> f)
        film_changed (Film::SIZE);
        film_changed (Film::LENGTH);
        film_changed (Film::FRAMES_PER_SECOND);
-       film_changed (Film::AUDIO_SAMPLE_RATE);
        film_changed (Film::SCALER);
        film_changed (Film::AUDIO_GAIN);
        film_changed (Film::AUDIO_DELAY);
        film_changed (Film::STILL_DURATION);
        film_changed (Film::WITH_SUBTITLES);
-       film_changed (Film::HAS_SUBTITLES);
        film_changed (Film::SUBTITLE_OFFSET);
        film_changed (Film::SUBTITLE_SCALE);
        film_changed (Film::USE_DCI_NAME);
@@ -911,7 +908,7 @@ FilmEditor::setup_subtitle_control_sensitivity ()
 {
        bool h = false;
        if (_generally_sensitive && _film) {
-               h = _film->has_subtitles();
+               h = !_film->subtitle_streams().empty();
        }
        
        _with_subtitles->Enable (h);
@@ -963,16 +960,21 @@ FilmEditor::setup_streams ()
        _audio_stream->Clear ();
        vector<AudioStream> a = _film->audio_streams ();
        for (vector<AudioStream>::iterator i = a.begin(); i != a.end(); ++i) {
-               _audio_stream->Append (std_to_wx (i->name()));
+               _audio_stream->Append (std_to_wx (i->name()), new wxStringClientData (std_to_wx (i->to_string ())));
+       }
+       
+       if (_film->audio_stream()) {
+               checked_set (_audio_stream, _film->audio_stream().get().to_string());
        }
-       _audio_stream->SetSelection (_film->audio_stream_index ());
 
        _subtitle_stream->Clear ();
        vector<SubtitleStream> s = _film->subtitle_streams ();
        for (vector<SubtitleStream>::iterator i = s.begin(); i != s.end(); ++i) {
-               _subtitle_stream->Append (std_to_wx (i->name()));
+               _subtitle_stream->Append (std_to_wx (i->name()), new wxStringClientData (std_to_wx (i->to_string ())));
+       }
+       if (_film->subtitle_stream()) {
+               checked_set (_subtitle_stream, _film->subtitle_stream().get().to_string());
        }
-       _subtitle_stream->SetSelection (_film->subtitle_stream_index ());
 }
 
 void
@@ -982,7 +984,7 @@ FilmEditor::audio_stream_changed (wxCommandEvent &)
                return;
        }
 
-       _film->set_audio_stream (_audio_stream->GetSelection ());
+       _film->set_audio_stream (AudioStream (string_client_data (_audio_stream->GetClientObject (_audio_stream->GetSelection ()))));
 }
 
 void
@@ -992,17 +994,17 @@ FilmEditor::subtitle_stream_changed (wxCommandEvent &)
                return;
        }
 
-       _film->set_subtitle_stream (_subtitle_stream->GetSelection ());
+       _film->set_subtitle_stream (SubtitleStream (string_client_data (_subtitle_stream->GetClientObject (_subtitle_stream->GetSelection ()))));
 }
 
 void
 FilmEditor::setup_audio_details ()
 {
-       if (_film->audio_channels() == 0 && _film->audio_sample_rate() == 0) {
+       if (!_film->audio_stream()) {
                _audio->SetLabel (wxT (""));
        } else {
                stringstream s;
-               s << _film->audio_channels () << " channels, " << _film->audio_sample_rate() << "Hz";
+               s << _film->audio_stream().get().channels () << " channels, " << _film->audio_stream().get().sample_rate() << "Hz";
                _audio->SetLabel (std_to_wx (s.str ()));
        }
 }
index d3bfa2702edb12607a7ae19143166c597d40ca0f..4196dd632e01ef1c4477fc89a31ff1a7994580b6 100644 (file)
@@ -109,6 +109,12 @@ ThreadedStaticText::thread_finished (wxCommandEvent& ev)
        SetLabel (ev.GetString ());
 }
 
+string
+string_client_data (wxClientData* o)
+{
+       return wx_to_std (dynamic_cast<wxStringClientData*>(o)->GetData());
+}
+
 void
 checked_set (wxFilePickerCtrl* widget, string value)
 {
@@ -133,6 +139,20 @@ checked_set (wxComboBox* widget, int value)
        }
 }
 
+void
+checked_set (wxComboBox* widget, string value)
+{
+       wxClientData* o = widget->GetClientObject (widget->GetSelection ());
+       
+       if (!o || string_client_data(o) != value) {
+               for (unsigned int i = 0; i < widget->GetCount(); ++i) {
+                       if (string_client_data (widget->GetClientObject (i)) == value) {
+                               widget->SetSelection (i);
+                       }
+               }
+       }
+}
+
 void
 checked_set (wxTextCtrl* widget, string value)
 {
index 5cd3e5a7fcbee104c058dc8837486dc65aad2aa2..6cb7fd00290e8abf553ceade48d651818e440716 100644 (file)
@@ -54,9 +54,12 @@ private:
        static const int _update_event_id;
 };
 
+extern std::string string_client_data (wxClientData* o);
+
 extern void checked_set (wxFilePickerCtrl* widget, std::string value);
 extern void checked_set (wxSpinCtrl* widget, int value);
 extern void checked_set (wxComboBox* widget, int value);
+extern void checked_set (wxComboBox* widget, std::string value);
 extern void checked_set (wxTextCtrl* widget, std::string value);
 extern void checked_set (wxCheckBox* widget, bool value);
 extern void checked_set (wxRadioButton* widget, bool value);
index d1286dd762b9e966e5356ebfeb54509c9c4cfd77..3a1d6f7d47f1b42db6b0fcfaeab5f8c77fd18065 100644 (file)
@@ -411,21 +411,21 @@ BOOST_AUTO_TEST_CASE (audio_sampling_rate_test)
        shared_ptr<Film> f = new_test_film ("audio_sampling_rate_test");
        f->set_frames_per_second (24);
 
-       f->set_audio_sample_rate (48000);
+       f->set_audio_stream (AudioStream ("a", 42, 48000, 0));
        BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 48000);
 
-       f->set_audio_sample_rate (44100);
+       f->set_audio_stream (AudioStream ("a", 42, 44100, 0));
        BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 48000);
 
-       f->set_audio_sample_rate (80000);
+       f->set_audio_stream (AudioStream ("a", 42, 80000, 0));
        BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 96000);
 
        f->set_frames_per_second (23.976);
-       f->set_audio_sample_rate (48000);
+       f->set_audio_stream (AudioStream ("a", 42, 48000, 0));
        BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 47952);
 
        f->set_frames_per_second (29.97);
-       f->set_audio_sample_rate (48000);
+       f->set_audio_stream (AudioStream ("a", 42, 48000, 0));
        BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 47952);
 }