summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2012-12-15 18:16:35 +0000
committerCarl Hetherington <cth@carlh.net>2012-12-15 18:16:35 +0000
commit89319eb1217c8caca80dc22ca770766f6d2f26c0 (patch)
tree32a5837e1f1ecbe370890169d4289fc649173a7a /src
parent0b781dd65a90e617866810ecb3dee27267449f1f (diff)
Skipping hacks.
Diffstat (limited to 'src')
-rw-r--r--src/lib/encoder.cc5
-rw-r--r--src/lib/ffmpeg_decoder.cc109
-rw-r--r--src/lib/ffmpeg_decoder.h3
-rw-r--r--src/lib/film.cc2
-rw-r--r--src/lib/imagemagick_encoder.cc3
-rw-r--r--src/lib/options.h9
-rw-r--r--src/lib/transcoder.cc6
-rw-r--r--src/lib/transcoder.h2
-rw-r--r--src/wx/wx_util.cc5
9 files changed, 95 insertions, 49 deletions
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index 17a6726a6..dfb154f72 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -107,11 +107,6 @@ Encoder::frame_skipped ()
void
Encoder::process_video (shared_ptr<Image> i, boost::shared_ptr<Subtitle> s)
{
- if (_opt->decode_video_skip != 0 && (_video_frame % _opt->decode_video_skip) != 0) {
- ++_video_frame;
- return;
- }
-
if (_opt->video_decode_range) {
pair<SourceFrame, SourceFrame> const r = _opt->video_decode_range.get();
if (_video_frame < r.first || _video_frame >= r.second) {
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index acaf149f4..1e473b6a3 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -265,46 +265,10 @@ FFmpegDecoder::pass ()
_film->log()->log (String::compose ("Used only %1 bytes of %2 in packet", r, _packet.size));
}
- /* Where we are in the output, in seconds */
- double const out_pts_seconds = video_frame() / frames_per_second();
-
- /* Where we are in the source, in seconds */
- double const source_pts_seconds = av_q2d (_format_context->streams[_packet.stream_index]->time_base)
- * av_frame_get_best_effort_timestamp(_frame);
-
- _film->log()->log (
- String::compose ("Source video frame ready; source at %1, output at %2", source_pts_seconds, out_pts_seconds),
- Log::VERBOSE
- );
-
- if (!_first_video) {
- _first_video = source_pts_seconds;
- }
-
- /* Difference between where we are and where we should be */
- double const delta = source_pts_seconds - _first_video.get() - out_pts_seconds;
- double const one_frame = 1 / frames_per_second();
-
- /* Insert frames if required to get out_pts_seconds up to pts_seconds */
- if (delta > one_frame) {
- int const extra = rint (delta / one_frame);
- for (int i = 0; i < extra; ++i) {
- repeat_last_video ();
- _film->log()->log (
- String::compose (
- "Extra video frame inserted at %1s; source frame %2, source PTS %3 (at %4 fps)",
- out_pts_seconds, video_frame(), source_pts_seconds, frames_per_second()
- )
- );
- }
- }
-
- if (delta > -one_frame) {
- /* Process this frame */
- filter_and_emit_video (_frame);
+ if (_opt->rough_decode_video_skip) {
+ rough_video_output ();
} else {
- /* Otherwise we are omitting a frame to keep things right */
- _film->log()->log (String::compose ("Frame removed at %1s", out_pts_seconds));
+ precise_video_output ();
}
}
@@ -637,3 +601,70 @@ FFmpegDecoder::length () const
{
return (double(_format_context->duration) / AV_TIME_BASE) * frames_per_second();
}
+
+void
+FFmpegDecoder::precise_video_output ()
+{
+ /* Where we are in the output, in seconds */
+ double const out_pts_seconds = video_frame() / frames_per_second();
+
+ /* Where we are in the source, in seconds */
+ double const source_pts_seconds = av_q2d (_format_context->streams[_packet.stream_index]->time_base)
+ * av_frame_get_best_effort_timestamp(_frame);
+
+ _film->log()->log (
+ String::compose ("Source video frame ready; source at %1, output at %2", source_pts_seconds, out_pts_seconds),
+ Log::VERBOSE
+ );
+
+ if (!_first_video) {
+ _first_video = source_pts_seconds;
+ }
+
+ /* Difference between where we are and where we should be */
+ double const delta = source_pts_seconds - _first_video.get() - out_pts_seconds;
+ double const one_frame = 1 / frames_per_second();
+
+ /* Insert frames if required to get out_pts_seconds up to pts_seconds */
+ if (delta > one_frame) {
+ int const extra = rint (delta / one_frame);
+ for (int i = 0; i < extra; ++i) {
+ repeat_last_video ();
+ _film->log()->log (
+ String::compose (
+ "Extra video frame inserted at %1s; source frame %2, source PTS %3 (at %4 fps)",
+ out_pts_seconds, video_frame(), source_pts_seconds, frames_per_second()
+ )
+ );
+ }
+ }
+
+ if (delta > -one_frame) {
+ /* Process this frame */
+ filter_and_emit_video (_frame);
+ } else {
+ /* Otherwise we are omitting a frame to keep things right */
+ _film->log()->log (String::compose ("Frame removed at %1s", out_pts_seconds));
+ }
+}
+
+void
+FFmpegDecoder::rough_video_output ()
+{
+ /* Where we are in the source, in seconds */
+ double const source_pts_seconds = av_q2d (_format_context->streams[_packet.stream_index]->time_base)
+ * av_frame_get_best_effort_timestamp(_frame);
+
+ if (!_last_rough_output || _last_rough_output.get() != source_pts_seconds) {
+ filter_and_emit_video (_frame);
+ _last_rough_output = source_pts_seconds;
+ }
+
+ int64_t const t = static_cast<int64_t>(f) / (av_q2d (_format_context->streams[_video_stream]->time_base) * frames_per_second());
+ cout << "seek to " << t << " in stream tb\n";
+ int const r = av_seek_frame (_format_context, _video_stream, t, 0);
+ avcodec_flush_buffers (_video_codec_context);
+ if (r < 0) {
+ cout << "seek to " << t << " failed.\n";
+ }
+}
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index 1771551fc..141b40da0 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -105,6 +105,8 @@ private:
AVSampleFormat audio_sample_format () const;
int bytes_per_audio_sample () const;
+ void rough_video_output ();
+ void precise_video_output ();
void filter_and_emit_video (AVFrame *);
void setup_general ();
@@ -133,6 +135,7 @@ private:
boost::optional<double> _first_video;
boost::optional<double> _first_audio;
+ boost::optional<double> _last_rough_output;
std::list<boost::shared_ptr<FilterGraph> > _filter_graphs;
};
diff --git a/src/lib/film.cc b/src/lib/film.cc
index e2a4cbeda..ecf37f033 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -1003,7 +1003,7 @@ Film::set_trust_content_header (bool t)
signal_changed (TRUST_CONTENT_HEADER);
- if (!_trust_content_header) && !content().empty()) {
+ if (!_trust_content_header && !content().empty()) {
/* We just said that we don't trust the content's header */
examine_content ();
}
diff --git a/src/lib/imagemagick_encoder.cc b/src/lib/imagemagick_encoder.cc
index 480dec8bc..4fa702369 100644
--- a/src/lib/imagemagick_encoder.cc
+++ b/src/lib/imagemagick_encoder.cc
@@ -38,6 +38,7 @@
using std::string;
using std::ofstream;
+using std::cout;
using boost::shared_ptr;
/** @param f Film that we are encoding.
@@ -55,6 +56,8 @@ ImageMagickEncoder::do_process_video (shared_ptr<Image> image, shared_ptr<Subtit
shared_ptr<Image> scaled = image->scale_and_convert_to_rgb (_opt->out_size, _opt->padding, _film->scaler());
shared_ptr<Image> compact (new CompactImage (scaled));
+ cout << "IME writes frame " << _video_frame << "\n";
+
string tmp_file = _opt->frame_out_path (_video_frame, true);
Magick::Image thumb (compact->size().width, compact->size().height, "RGB", MagickCore::CharPixel, compact->data()[0]);
thumb.magick ("PNG");
diff --git a/src/lib/options.h b/src/lib/options.h
index 29b3b71cd..2fc3e5599 100644
--- a/src/lib/options.h
+++ b/src/lib/options.h
@@ -104,9 +104,14 @@ public:
boost::optional<std::pair<int64_t, int64_t> > audio_decode_range;
/** Skip frames such that we don't decode any frame where (index % decode_video_skip) != 0; e.g.
- * 1 for every frame, 2 for every other frame, etc.
+ * 1 for every frame, 2 for every other frame, etc. With the `precise' skip, we do it
+ * by running the decoder without seeking and throwing away frames that we don't want.
*/
- SourceFrame decode_video_skip;
+ boost::optional<SourceFrame> precise_decode_video_skip;
+ /** As for precise_decode_video_skip, except that it is achieved by skipping the decoder, so
+ * things are made less precise by the presence of keyframes and other complications.
+ */
+ boost::optional<SourceFrame> rough_decode_video_skip;
bool decode_audio; ///< true to decode audio, otherwise false
bool decode_subtitles;
diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc
index a7e79b05f..f764c65fb 100644
--- a/src/lib/transcoder.cc
+++ b/src/lib/transcoder.cc
@@ -49,7 +49,9 @@ using boost::dynamic_pointer_cast;
* @param e Encoder to use.
*/
Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j, shared_ptr<Encoder> e)
- : _job (j)
+ : _film (f)
+ , _opt (o)
+ , _job (j)
, _encoder (e)
, _decoders (decoder_factory (f, o, j))
{
@@ -90,6 +92,8 @@ void
Transcoder::go ()
{
_encoder->process_begin ();
+ SourceFrame s = 0;
+
try {
bool done[2] = { false, false };
diff --git a/src/lib/transcoder.h b/src/lib/transcoder.h
index 4a9667b3c..43c70df00 100644
--- a/src/lib/transcoder.h
+++ b/src/lib/transcoder.h
@@ -54,6 +54,8 @@ public:
}
protected:
+ boost::shared_ptr<Film> _film;
+ boost::shared_ptr<const Options> _opt;
/** A Job that is running this Transcoder, or 0 */
Job* _job;
/** The encoder that we will use */
diff --git a/src/wx/wx_util.cc b/src/wx/wx_util.cc
index 186e9c86b..b9a462801 100644
--- a/src/wx/wx_util.cc
+++ b/src/wx/wx_util.cc
@@ -155,7 +155,10 @@ checked_set (wxComboBox* widget, int value)
void
checked_set (wxComboBox* widget, string value)
{
- wxClientData* o = widget->GetClientObject (widget->GetSelection ());
+ wxClientData* o = 0;
+ if (widget->GetSelection() != -1) {
+ o = widget->GetClientObject (widget->GetSelection ());
+ }
if (!o || string_client_data(o) != value) {
for (unsigned int i = 0; i < widget->GetCount(); ++i) {