summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2012-10-17 13:47:50 +0100
committerCarl Hetherington <cth@carlh.net>2012-10-17 13:47:50 +0100
commit4dfce74792c3ea55ecf2479568f76d7e54b826e0 (patch)
treed21aa7e386be12027239c4a1f5a25e6f42d04b8b /src/lib
parent91e8c79235abccac95c63952192fd63840727f99 (diff)
Basic support for selection of audio / subtitle streams.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/decoder.h12
-rw-r--r--src/lib/ffmpeg_decoder.cc61
-rw-r--r--src/lib/ffmpeg_decoder.h12
-rw-r--r--src/lib/film.cc6
-rw-r--r--src/lib/film.h18
-rw-r--r--src/lib/film_state.cc60
-rw-r--r--src/lib/film_state.h7
-rw-r--r--src/lib/stream.cc41
-rw-r--r--src/lib/stream.h39
-rw-r--r--src/lib/wscript1
10 files changed, 234 insertions, 23 deletions
diff --git a/src/lib/decoder.h b/src/lib/decoder.h
index 8a04ec9f2..312cbbe8e 100644
--- a/src/lib/decoder.h
+++ b/src/lib/decoder.h
@@ -30,6 +30,7 @@
#include <boost/shared_ptr.hpp>
#include <sigc++/sigc++.h>
#include "util.h"
+#include "stream.h"
class Job;
class FilmState;
@@ -79,6 +80,17 @@ public:
int last_video_frame () const {
return _video_frame;
}
+
+ virtual std::vector<Stream> audio_streams () const {
+ return std::vector<Stream> ();
+ }
+
+ virtual std::vector<Stream> subtitle_streams () const {
+ return std::vector<Stream> ();
+ }
+
+ 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.
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index e85439f6e..4cec7ef35 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -110,9 +110,15 @@ FFmpegDecoder::setup_general ()
if (_format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
_video_stream = i;
} else if (_format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
- _audio_stream = i;
+ 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) {
- _subtitle_stream = i;
+ if (_subtitle_stream == -1) {
+ _subtitle_stream = i;
+ }
+ _subtitle_streams.push_back (Stream (stream_name (_format_context->streams[i]), i));
}
}
@@ -356,3 +362,54 @@ FFmpegDecoder::has_subtitles () const
{
return (_subtitle_stream != -1);
}
+
+vector<Stream>
+FFmpegDecoder::audio_streams () const
+{
+ return _audio_streams;
+}
+
+vector<Stream>
+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
+{
+ stringstream n;
+
+ AVDictionaryEntry const * lang = av_dict_get (s->metadata, "language", 0, 0);
+ if (lang) {
+ n << lang->value;
+ }
+
+ AVDictionaryEntry const * title = av_dict_get (s->metadata, "title", 0, 0);
+ if (title) {
+ if (!n.str().empty()) {
+ n << " ";
+ }
+ n << title->value;
+ }
+
+ if (n.str().empty()) {
+ n << "unknown";
+ }
+
+ return n.str ();
+}
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index ec822bf79..9abc7f49a 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -39,6 +39,7 @@ struct AVFormatContext;
struct AVFrame;
struct AVBufferContext;
struct AVCodec;
+struct AVStream;
class Job;
class FilmState;
class Options;
@@ -65,6 +66,12 @@ public:
int64_t audio_channel_layout () const;
bool has_subtitles () 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);
+
private:
bool do_pass ();
@@ -81,11 +88,16 @@ private:
void maybe_add_subtitle ();
+ std::string stream_name (AVStream* s) const;
+
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<Stream> _audio_streams;
+ std::vector<Stream> _subtitle_streams;
AVCodecContext* _video_codec_context;
AVCodec* _video_codec;
diff --git a/src/lib/film.cc b/src/lib/film.cc
index ce83b1324..9e1640d58 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -201,6 +201,10 @@ Film::set_content (string c)
_state.audio_sample_rate = d->audio_sample_rate ();
_state.audio_sample_format = d->audio_sample_format ();
_state.has_subtitles = d->has_subtitles ();
+ _state.audio_streams = d->audio_streams ();
+ _state.subtitle_streams = d->subtitle_streams ();
+ _state.audio_stream = _state.audio_streams.empty() ? -1 : _state.audio_streams.front().id;
+ _state.subtitle_stream = _state.subtitle_streams.empty() ? -1 : _state.subtitle_streams.front().id;
_state.content_digest = md5_digest (s->content_path ());
_state.content = c;
@@ -211,6 +215,8 @@ Film::set_content (string c)
signal_changed (AUDIO_CHANNELS);
signal_changed (AUDIO_SAMPLE_RATE);
signal_changed (CONTENT);
+ signal_changed (AUDIO_STREAM);
+ signal_changed (SUBTITLE_STREAM);
}
/** Set the format that this Film should be shown in */
diff --git a/src/lib/film.h b/src/lib/film.h
index ae0ad7ad1..deff4b8a8 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -162,6 +162,22 @@ public:
return _state.dcp_content_type;
}
+ std::vector<Stream> audio_streams () const {
+ return _state.audio_streams;
+ }
+
+ int audio_stream () const {
+ return _state.audio_stream;
+ }
+
+ std::vector<Stream> subtitle_streams () const {
+ return _state.subtitle_streams;
+ }
+
+ int subtitle_stream () const {
+ return _state.subtitle_stream;
+ }
+
void set_dcp_frames (int);
void set_dcp_trim_action (TrimAction);
void set_dcp_ab (bool);
@@ -287,6 +303,7 @@ public:
DCP_FRAMES,
DCP_TRIM_ACTION,
DCP_AB,
+ AUDIO_STREAM,
AUDIO_GAIN,
AUDIO_DELAY,
THUMBS,
@@ -296,6 +313,7 @@ public:
AUDIO_CHANNELS,
AUDIO_SAMPLE_RATE,
STILL_DURATION,
+ SUBTITLE_STREAM,
WITH_SUBTITLES,
SUBTITLE_OFFSET,
SUBTITLE_SCALE,
diff --git a/src/lib/film_state.cc b/src/lib/film_state.cc
index aa8bb5563..0d0bd6313 100644
--- a/src/lib/film_state.cc
+++ b/src/lib/film_state.cc
@@ -79,12 +79,20 @@ FilmState::write_metadata (ofstream& f) const
}
f << "dcp_ab " << (dcp_ab ? "1" : "0") << "\n";
+ f << "selected_audio_stream " << audio_stream << "\n";
f << "audio_gain " << audio_gain << "\n";
f << "audio_delay " << audio_delay << "\n";
f << "still_duration " << still_duration << "\n";
f << "with_subtitles " << with_subtitles << "\n";
f << "subtitle_offset " << subtitle_offset << "\n";
f << "subtitle_scale " << subtitle_scale << "\n";
+ f << "audio_language " << audio_language << "\n";
+ f << "subtitle_language " << subtitle_language << "\n";
+ f << "territory " << territory << "\n";
+ f << "rating " << rating << "\n";
+ f << "studio " << studio << "\n";
+ f << "facility " << facility << "\n";
+ f << "package_type " << package_type << "\n";
/* Cached stuff; this is information about our content; we could
look it up each time, but that's slow.
@@ -99,14 +107,16 @@ FilmState::write_metadata (ofstream& f) const
f << "audio_sample_rate " << audio_sample_rate << "\n";
f << "audio_sample_format " << audio_sample_format_to_string (audio_sample_format) << "\n";
f << "content_digest " << content_digest << "\n";
+ f << "selected_subtitle_stream " << subtitle_stream << "\n";
f << "has_subtitles " << has_subtitles << "\n";
- f << "audio_language " << audio_language << "\n";
- f << "subtitle_language " << subtitle_language << "\n";
- f << "territory " << territory << "\n";
- f << "rating " << rating << "\n";
- f << "studio " << studio << "\n";
- f << "facility " << facility << "\n";
- f << "package_type " << package_type << "\n";
+
+ for (vector<Stream>::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) {
+ f << "subtitle_stream " << i->to_string () << "\n";
+ }
}
/** Read state from a key / value pair.
@@ -151,6 +161,8 @@ FilmState::read_metadata (string k, string v)
}
} else if (k == "dcp_ab") {
dcp_ab = (v == "1");
+ } else if (k == "selected_audio_stream") {
+ audio_stream = atoi (v.c_str ());
} else if (k == "audio_gain") {
audio_gain = atof (v.c_str ());
} else if (k == "audio_delay") {
@@ -163,6 +175,22 @@ FilmState::read_metadata (string k, string v)
subtitle_offset = atoi (v.c_str ());
} else if (k == "subtitle_scale") {
subtitle_scale = atof (v.c_str ());
+ } else if (k == "selected_subtitle_stream") {
+ subtitle_stream = atoi (v.c_str ());
+ } else if (k == "audio_language") {
+ audio_language = v;
+ } else if (k == "subtitle_language") {
+ subtitle_language = v;
+ } else if (k == "territory") {
+ territory = v;
+ } else if (k == "rating") {
+ rating = v;
+ } else if (k == "studio") {
+ studio = v;
+ } else if (k == "facility") {
+ facility = v;
+ } else if (k == "package_type") {
+ package_type = v;
}
/* Cached stuff */
@@ -188,20 +216,10 @@ FilmState::read_metadata (string k, string v)
content_digest = v;
} else if (k == "has_subtitles") {
has_subtitles = (v == "1");
- } else if (k == "audio_language") {
- audio_language = v;
- } else if (k == "subtitle_language") {
- subtitle_language = v;
- } else if (k == "territory") {
- territory = v;
- } else if (k == "rating") {
- rating = v;
- } else if (k == "studio") {
- studio = v;
- } else if (k == "facility") {
- facility = v;
- } else if (k == "package_type") {
- package_type = v;
+ } else if (k == "audio_stream") {
+ audio_streams.push_back (Stream (v));
+ } else if (k == "subtitle_stream") {
+ subtitle_streams.push_back (Stream (v));
}
}
diff --git a/src/lib/film_state.h b/src/lib/film_state.h
index ea287fb3b..38176f224 100644
--- a/src/lib/film_state.h
+++ b/src/lib/film_state.h
@@ -34,6 +34,7 @@ extern "C" {
#include "scaler.h"
#include "util.h"
#include "trim_action.h"
+#include "stream.h"
class Format;
class DCPContentType;
@@ -60,9 +61,11 @@ public:
, dcp_frames (0)
, dcp_trim_action (CUT)
, dcp_ab (false)
+ , audio_stream (-1)
, audio_gain (0)
, audio_delay (0)
, still_duration (10)
+ , subtitle_stream (-1)
, with_subtitles (false)
, subtitle_offset (0)
, subtitle_scale (1)
@@ -130,12 +133,14 @@ public:
has the specified filters and post-processing.
*/
bool dcp_ab;
+ int audio_stream;
/** Gain to apply to audio in dB */
float audio_gain;
/** Delay to apply to audio (positive moves audio later) in milliseconds */
int audio_delay;
/** Duration to make still-sourced films (in seconds) */
int still_duration;
+ int 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
@@ -172,6 +177,8 @@ public:
std::string content_digest;
/** true if the source has subtitles */
bool has_subtitles;
+ std::vector<Stream> audio_streams;
+ std::vector<Stream> subtitle_streams;
private:
std::string thumb_file_for_frame (int) const;
diff --git a/src/lib/stream.cc b/src/lib/stream.cc
new file mode 100644
index 000000000..e40738990
--- /dev/null
+++ b/src/lib/stream.cc
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <sstream>
+#include "compose.hpp"
+#include "stream.h"
+
+using namespace std;
+
+Stream::Stream (string t)
+{
+ stringstream n (t);
+ n >> id;
+
+ size_t const s = t.find (' ');
+ if (s != string::npos) {
+ name = t.substr (s + 1);
+ }
+}
+
+string
+Stream::to_string () const
+{
+ return String::compose ("%1 %2", id, name);
+}
diff --git a/src/lib/stream.h b/src/lib/stream.h
new file mode 100644
index 000000000..764c03d79
--- /dev/null
+++ b/src/lib/stream.h
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef DVDOMATIC_STREAM_H
+#define DVDOMATIC_STREAM_H
+
+struct Stream
+{
+public:
+ Stream (std::string t);
+
+ Stream (std::string n, int i)
+ : name (n)
+ , id (i)
+ {}
+
+ std::string to_string () const;
+
+ std::string name;
+ int id;
+};
+
+#endif
diff --git a/src/lib/wscript b/src/lib/wscript
index 63847224c..6ce216d81 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -43,6 +43,7 @@ def build(bld):
screen.cc
server.cc
sound_processor.cc
+ stream.cc
subtitle.cc
thumbs_job.cc
tiff_decoder.cc