void
ABTranscoder::go ()
{
- _encoder->process_begin (_da->audio_channel_layout(), _da->audio_sample_format());
+ _encoder->process_begin (_da->audio_channel_layout());
_da->process_begin ();
_db->process_begin ();
return _video_frame;
}
- virtual std::vector<Stream> audio_streams () const {
- return std::vector<Stream> ();
+ virtual std::vector<AudioStream> audio_streams () const {
+ return std::vector<AudioStream> ();
}
- virtual std::vector<Stream> subtitle_streams () const {
- return std::vector<Stream> ();
+ virtual std::vector<SubtitleStream> subtitle_streams () const {
+ return std::vector<SubtitleStream> ();
}
- virtual void set_audio_stream (Stream s) {}
- virtual void set_subtitle_stream (Stream s) {}
-
/** Emitted when a video frame is ready.
* First parameter is the frame.
* Second parameter is its index within the content.
Encoder (boost::shared_ptr<const FilmState> s, boost::shared_ptr<const Options> o, Log* l);
/** Called to indicate that a processing run is about to begin */
- virtual void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format) = 0;
+ virtual void process_begin (int64_t audio_channel_layout) = 0;
/** Called with a frame of video.
* @param i Video frame image.
/* Find video, audio and subtitle streams and choose the first of each */
for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
- if (_format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ AVStream* s = _format_context->streams[i];
+ if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
_video_stream = i;
- } else if (_format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+ } else if (s->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
if (_audio_stream == -1) {
_audio_stream = i;
}
- _audio_streams.push_back (Stream (stream_name (_format_context->streams[i]), i));
- } else if (_format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+ _audio_streams.push_back (AudioStream (stream_name (s), i, s->codec->channels));
+ } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
if (_subtitle_stream == -1) {
_subtitle_stream = i;
}
- _subtitle_streams.push_back (Stream (stream_name (_format_context->streams[i]), 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 (_fs->audio_stream() != -1) {
- vector<Stream>::iterator i = _audio_streams.begin ();
- while (i != _audio_streams.end() && i->id != _fs->audio_stream()) {
- ++i;
- }
-
- if (i != _audio_streams.end()) {
- _audio_stream = _fs->audio_stream ();
- }
+ if (_fs->audio_stream_index() != -1) {
+ _audio_stream = _fs->audio_stream_decoder_id ();
}
- if (_fs->subtitle_stream() != -1) {
- vector<Stream>::iterator i = _subtitle_streams.begin ();
- while (i != _subtitle_streams.end() && i->id != _fs->subtitle_stream()) {
- ++i;
- }
-
- if (i != _subtitle_streams.end()) {
- _subtitle_stream = _fs->subtitle_stream ();
- }
+ if (_fs->subtitle_stream_index() != -1) {
+ _subtitle_stream = _fs->subtitle_stream_decoder_id ();
}
if (_video_stream < 0) {
return (_subtitle_stream != -1);
}
-vector<Stream>
+vector<AudioStream>
FFmpegDecoder::audio_streams () const
{
return _audio_streams;
}
-vector<Stream>
+vector<SubtitleStream>
FFmpegDecoder::subtitle_streams () const
{
return _subtitle_streams;
}
-void
-FFmpegDecoder::set_audio_stream (int s)
-{
- _audio_stream = s;
- setup_audio ();
-}
-
-void
-FFmpegDecoder::set_subtitle_stream (int s)
-{
- _subtitle_stream = s;
- setup_subtitle ();
-}
-
string
FFmpegDecoder::stream_name (AVStream* s) const
{
bool has_subtitles () const;
int bytes_per_audio_sample () const;
- std::vector<Stream> audio_streams () const;
- std::vector<Stream> subtitle_streams () const;
-
- void set_audio_stream (int id);
- void set_subtitle_stream (int id);
+ std::vector<AudioStream> audio_streams () const;
+ std::vector<SubtitleStream> subtitle_streams () const;
private:
int _subtitle_stream; ///< may be < 0 if there is no subtitle
AVFrame* _frame;
- std::vector<Stream> _audio_streams;
- std::vector<Stream> _subtitle_streams;
+ std::vector<AudioStream> _audio_streams;
+ std::vector<SubtitleStream> _subtitle_streams;
AVCodecContext* _video_codec_context;
AVCodec* _video_codec;
f << "width " << _size.width << "\n";
f << "height " << _size.height << "\n";
f << "length " << _length << "\n";
- f << "audio_channels " << _audio_channels << "\n";
f << "audio_sample_rate " << _audio_sample_rate << "\n";
f << "content_digest " << _content_digest << "\n";
f << "has_subtitles " << _has_subtitles << "\n";
- for (vector<Stream>::const_iterator i = _audio_streams.begin(); i != _audio_streams.end(); ++i) {
+ for (vector<AudioStream>::const_iterator i = _audio_streams.begin(); i != _audio_streams.end(); ++i) {
f << "audio_stream " << i->to_string () << "\n";
}
- for (vector<Stream>::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) {
+ for (vector<SubtitleStream>::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) {
f << "subtitle_stream " << i->to_string () << "\n";
}
_size.height = atoi (v.c_str ());
} else if (k == "length") {
_length = atof (v.c_str ());
- } else if (k == "audio_channels") {
- _audio_channels = atoi (v.c_str ());
} else if (k == "audio_sample_rate") {
_audio_sample_rate = atoi (v.c_str ());
} else if (k == "content_digest") {
} else if (k == "has_subtitles") {
_has_subtitles = (v == "1");
} else if (k == "audio_stream") {
- _audio_streams.push_back (Stream (v));
+ _audio_streams.push_back (AudioStream (v));
} else if (k == "subtitle_stream") {
- _subtitle_streams.push_back (Stream (v));
+ _subtitle_streams.push_back (SubtitleStream (v));
} else if (k == "frames_per_second") {
_frames_per_second = atof (v.c_str ());
}
d << "_";
}
- switch (_audio_channels) {
+ switch (_audio_streams[_audio_stream].channels()) {
case 1:
d << "10_";
break;
set_size (d->native_size ());
set_length (d->length_in_frames ());
set_frames_per_second (d->frames_per_second ());
- set_audio_channels (d->audio_channels ());
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 : audio_streams().front().id);
- set_subtitle_stream (subtitle_streams().empty() ? -1 : subtitle_streams().front().id);
+ set_audio_stream (audio_streams().empty() ? -1 : 0);
+ set_subtitle_stream (subtitle_streams().empty() ? -1 : 0);
set_content_digest (md5_digest (content_path ()));
_content = c;
signal_changed (LENGTH);
}
-void
-FilmState::set_audio_channels (int c)
-{
- _audio_channels = c;
- signal_changed (AUDIO_CHANNELS);
-}
-
void
FilmState::set_audio_sample_rate (int r)
{
}
void
-FilmState::set_audio_streams (vector<Stream> s)
+FilmState::set_audio_streams (vector<AudioStream> s)
{
_audio_streams = s;
_dirty = true;
}
void
-FilmState::set_subtitle_streams (vector<Stream> s)
+FilmState::set_subtitle_streams (vector<SubtitleStream> s)
{
_subtitle_streams = s;
_dirty = true;
{
return shared_ptr<FilmState> (new FilmState (*this));
}
+
+int
+FilmState::audio_channels () const
+{
+ if (_audio_stream == -1) {
+ return 0;
+ }
+
+ return _audio_streams[_audio_stream].channels ();
+}
+
+
+
, _subtitle_offset (0)
, _subtitle_scale (1)
, _length (0)
- , _audio_channels (0)
, _audio_sample_rate (0)
, _has_subtitles (false)
, _frames_per_second (0)
return _dirty;
}
+ int audio_channels () const;
+
enum Property {
NONE,
NAME,
THUMBS,
SIZE,
LENGTH,
- AUDIO_CHANNELS,
AUDIO_SAMPLE_RATE,
HAS_SUBTITLES,
AUDIO_STREAMS,
return _dcp_ab;
}
- int audio_stream () const {
+ int audio_stream_index () const {
return _audio_stream;
}
+ int audio_stream_decoder_id () const {
+ assert (_audio_stream < int (_audio_streams.size()));
+ return _audio_streams[_audio_stream].id ();
+ }
+
float audio_gain () const {
return _audio_gain;
}
return _still_duration;
}
- int subtitle_stream () const {
+ int subtitle_stream_index () const {
return _subtitle_stream;
}
+ int subtitle_stream_decoder_id () const {
+ assert (_subtitle_stream < int (_subtitle_streams.size()));
+ return _subtitle_streams[_subtitle_stream].id ();
+ }
+
bool with_subtitles () const {
return _with_subtitles;
}
return _length;
}
- int audio_channels () const {
- return _audio_channels;
- }
-
int audio_sample_rate () const {
return _audio_sample_rate;
}
return _has_subtitles;
}
- std::vector<Stream> audio_streams () const {
+ std::vector<AudioStream> audio_streams () const {
return _audio_streams;
}
- std::vector<Stream> subtitle_streams () const {
+ std::vector<SubtitleStream> subtitle_streams () const {
return _subtitle_streams;
}
void set_audio_sample_rate (int);
void set_content_digest (std::string);
void set_has_subtitles (bool);
- void set_audio_streams (std::vector<Stream>);
- void set_subtitle_streams (std::vector<Stream>);
+ void set_audio_streams (std::vector<AudioStream>);
+ void set_subtitle_streams (std::vector<SubtitleStream>);
void set_frames_per_second (float);
/** Emitted when some property has changed */
has the specified filters and post-processing.
*/
bool _dcp_ab;
- /** The decoder's stream ID to use for audio, or -1 if there is none */
+ /** An index into our _audio_streams vector for the stream to use for audio, or -1 if there is none */
int _audio_stream;
/** Gain to apply to audio in dB */
float _audio_gain;
int _audio_delay;
/** Duration to make still-sourced films (in seconds) */
int _still_duration;
- /** The decoder's stream ID to use for subtitles, or -1 if there are none */
+ /** An index into our _subtitle_streams vector for the stream to use for subtitles, or -1 if there is none */
int _subtitle_stream;
/** True if subtitles should be shown for this film */
bool _with_subtitles;
Size _size;
/** Length of the source in frames */
int _length;
- /** Number of audio channels */
- int _audio_channels;
/** Sample rate of the source audio, in Hz */
int _audio_sample_rate;
/** MD5 digest of our content file */
/** true if the source has subtitles */
bool _has_subtitles;
/** the audio streams that the source has */
- std::vector<Stream> _audio_streams;
+ std::vector<AudioStream> _audio_streams;
/** the subtitle streams that the source has */
- std::vector<Stream> _subtitle_streams;
+ std::vector<SubtitleStream> _subtitle_streams;
/** Frames per second of the source */
float _frames_per_second;
public:
ImageMagickEncoder (boost::shared_ptr<const FilmState> s, boost::shared_ptr<const Options> o, Log* l);
- void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format) {}
+ void process_begin (int64_t audio_channel_layout) {}
void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>);
void process_audio (boost::shared_ptr<const AudioBuffers>) {}
void process_end () {}
public:
J2KStillEncoder (boost::shared_ptr<const FilmState>, boost::shared_ptr<const Options>, Log *);
- void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format) {}
+ void process_begin (int64_t audio_channel_layout) {}
void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>);
void process_audio (boost::shared_ptr<const AudioBuffers>) {}
void process_end () {}
}
void
-J2KWAVEncoder::process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format)
+J2KWAVEncoder::process_begin (int64_t audio_channel_layout)
{
if (_fs->audio_sample_rate() != _fs->target_sample_rate()) {
#ifdef HAVE_SWRESAMPLE
J2KWAVEncoder (boost::shared_ptr<const FilmState>, boost::shared_ptr<const Options>, Log *);
~J2KWAVEncoder ();
- void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format);
+ void process_begin (int64_t audio_channel_layout);
void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>);
void process_audio (boost::shared_ptr<const AudioBuffers>);
void process_end ();
using namespace std;
-Stream::Stream (string t)
+AudioStream::AudioStream (string t)
{
stringstream n (t);
- n >> id;
-
+ n >> _id >> _channels;
+
+ for (int i = 0; i < 2; ++i) {
+ size_t const s = t.find (' ');
+ if (s != string::npos) {
+ t = t.substr (s + 1);
+ }
+ }
+
+ _name = t;
+}
+
+string
+AudioStream::to_string () const
+{
+ return String::compose ("%1 %2 %3", _id, _channels, _name);
+}
+
+SubtitleStream::SubtitleStream (string t)
+{
+ stringstream n (t);
+ n >> _id;
+
size_t const s = t.find (' ');
if (s != string::npos) {
- name = t.substr (s + 1);
+ _name = t.substr (s + 1);
}
}
string
-Stream::to_string () const
+SubtitleStream::to_string () const
{
- return String::compose ("%1 %2", id, name);
+ return String::compose ("%1 %2", _id, _name);
}
#ifndef DVDOMATIC_STREAM_H
#define DVDOMATIC_STREAM_H
-struct Stream
+class Stream
{
public:
- Stream (std::string t);
+ Stream ()
+ : _id (-1)
+ {}
Stream (std::string n, int i)
- : name (n)
- , id (i)
+ : _name (n)
+ , _id (i)
{}
- std::string to_string () const;
+ virtual std::string to_string () const = 0;
- std::string name;
- int id;
+ std::string name () const {
+ return _name;
+ }
+
+ int id () const {
+ return _id;
+ }
+
+protected:
+ std::string _name;
+ int _id;
+};
+
+struct AudioStream : public Stream
+{
+public:
+ AudioStream (std::string t);
+
+ AudioStream (std::string n, int i, int c)
+ : Stream (n, i)
+ , _channels (c)
+ {}
+
+ std::string to_string () const;
+
+ int channels () const {
+ return _channels;
+ }
+
+private:
+ int _channels;
+};
+
+class SubtitleStream : public Stream
+{
+public:
+ SubtitleStream (std::string t);
+
+ SubtitleStream (std::string n, int i)
+ : Stream (n, i)
+ {}
+
+ std::string to_string () const;
};
#endif
void
Transcoder::go ()
{
- _encoder->process_begin (_decoder->audio_channel_layout(), _decoder->audio_sample_format());
+ _encoder->process_begin (_decoder->audio_channel_layout());
try {
_decoder->go ();
} catch (...) {
_frames_per_second->SetLabel (std_to_wx (s.str ()));
break;
}
- case FilmState::AUDIO_CHANNELS:
- _dcp_name->SetLabel (std_to_wx (_film->dcp_name ()));
case FilmState::AUDIO_SAMPLE_RATE:
if (_film->audio_channels() == 0 && _film->audio_sample_rate() == 0) {
_audio->SetLabel (wxT (""));
_dcp_name->SetLabel (std_to_wx (_film->dcp_name ()));
break;
case FilmState::AUDIO_STREAM:
- set_selected_stream (_film->audio_streams(), _film->audio_stream(), _audio_stream);
+ _dcp_name->SetLabel (std_to_wx (_film->dcp_name ()));
+ _audio_stream->SetSelection (_film->audio_stream_index ());
break;
case FilmState::SUBTITLE_STREAM:
- set_selected_stream (_film->subtitle_streams(), _film->subtitle_stream(), _subtitle_stream);
+ _subtitle_stream->SetSelection (_film->subtitle_stream_index ());
break;
}
}
film_changed (FilmState::SIZE);
film_changed (FilmState::LENGTH);
film_changed (FilmState::FRAMES_PER_SECOND);
- film_changed (FilmState::AUDIO_CHANNELS);
film_changed (FilmState::AUDIO_SAMPLE_RATE);
film_changed (FilmState::SCALER);
film_changed (FilmState::AUDIO_GAIN);
FilmEditor::setup_streams ()
{
_audio_stream->Clear ();
- vector<Stream> s = _film->audio_streams ();
- for (vector<Stream>::iterator i = s.begin(); i != s.end(); ++i) {
- _audio_stream->Append (std_to_wx (i->name));
+ 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()));
}
- set_selected_stream (_film->audio_streams(), _film->audio_stream(), _audio_stream);
+ _audio_stream->SetSelection (_film->audio_stream_index ());
_subtitle_stream->Clear ();
- s = _film->subtitle_streams ();
- for (vector<Stream>::iterator i = s.begin(); i != s.end(); ++i) {
- _subtitle_stream->Append (std_to_wx (i->name));
- }
- set_selected_stream (_film->subtitle_streams(), _film->subtitle_stream(), _subtitle_stream);
-}
-
-void
-FilmEditor::set_selected_stream (vector<Stream> const & streams, int id, wxComboBox* combo) const
-{
- if (id == -1) {
- return;
- }
-
- size_t n = 0;
- while (n < streams.size() && streams[n].id != id) {
- ++n;
+ 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()));
}
- assert (n < streams.size());
- combo->SetSelection (n);
+ _subtitle_stream->SetSelection (_film->subtitle_stream_index ());
}
void
}
_ignore_changes = Film::AUDIO_STREAM;
- int const n = _audio_stream->GetSelection ();
- if (n >= 0) {
- vector<Stream> s = _film->audio_streams ();
- assert (n < int (s.size ()));
- _film->set_audio_stream (s[n].id);
- }
+ _film->set_audio_stream (_audio_stream->GetSelection ());
_ignore_changes = Film::NONE;
}
}
_ignore_changes = Film::SUBTITLE_STREAM;
- int const n = _subtitle_stream->GetSelection ();
- if (n >= 0) {
- vector<Stream> s = _film->subtitle_streams ();
- assert (n < int (s.size ()));
- _film->set_subtitle_stream (s[n].id);
- }
+ _film->set_subtitle_stream (_subtitle_stream->GetSelection ());
_ignore_changes = Film::NONE;
}
void setup_formats ();
void setup_subtitle_button ();
void setup_streams ();
- void set_selected_stream (std::vector<Stream> const & streams, int id, wxComboBox* combo) const;
wxControl* video_control (wxControl *);
wxControl* still_control (wxControl *);
width 0
height 0
length 0
-audio_channels 0
audio_sample_rate 0
-audio_sample_format Unknown
content_digest
has_subtitles 0
frames_per_second 0
BOOST_CHECK_EQUAL (a->finished_in_error(), true);
BOOST_CHECK_EQUAL (b->running(), false);
}
+
+BOOST_AUTO_TEST_CASE (stream_test)
+{
+ AudioStream a ("4 9 hello there world");
+ BOOST_CHECK_EQUAL (a.id(), 4);
+ BOOST_CHECK_EQUAL (a.channels(), 9);
+ BOOST_CHECK_EQUAL (a.name(), "hello there world");
+ BOOST_CHECK_EQUAL (a.to_string(), "4 9 hello there world");
+
+ SubtitleStream s ("5 a b c");
+ BOOST_CHECK_EQUAL (s.id(), 5);
+ BOOST_CHECK_EQUAL (s.name(), "a b c");
+}