summaryrefslogtreecommitdiff
path: root/src/lib/ffmpeg_decoder.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-03-06 00:46:10 +0000
committerCarl Hetherington <cth@carlh.net>2013-03-06 00:46:10 +0000
commit59de84a29b81ac32477a4b804ca8bb9ec2760e67 (patch)
treeec0f37c766f2c65318c5b020818944614b101016 /src/lib/ffmpeg_decoder.cc
parent18614dda0d53b713ace5ad1df57298d049dba87f (diff)
First cut.
Diffstat (limited to 'src/lib/ffmpeg_decoder.cc')
-rw-r--r--src/lib/ffmpeg_decoder.cc126
1 files changed, 16 insertions, 110 deletions
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index 32c8e224a..f801821e9 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -80,10 +80,6 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr<Film> f, DecodeOptions o)
setup_video ();
setup_audio ();
setup_subtitle ();
-
- if (!o.video_sync) {
- _first_video = 0;
- }
}
FFmpegDecoder::~FFmpegDecoder ()
@@ -240,7 +236,7 @@ FFmpegDecoder::pass ()
if (_opt.decode_video) {
while (avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
- filter_and_emit_video (_frame);
+ filter_and_emit_video ();
}
}
@@ -265,16 +261,12 @@ FFmpegDecoder::pass ()
_film->log()->log (String::compose (N_("Used only %1 bytes of %2 in packet"), r, _packet.size));
}
- if (_opt.video_sync) {
- out_with_sync ();
- } else {
- filter_and_emit_video (_frame);
- }
+ filter_and_emit_video ();
}
} else if (ffa && _packet.stream_index == ffa->id() && _opt.decode_audio) {
decode_audio_packet ();
- } else if (_subtitle_stream && _packet.stream_index == _subtitle_stream->id() && _opt.decode_subtitles && _first_video) {
+ } else if (_subtitle_stream && _packet.stream_index == _subtitle_stream->id() && _opt.decode_subtitles) {
int got_subtitle;
AVSubtitle sub;
@@ -504,29 +496,29 @@ FFmpegDecoder::set_subtitle_stream (shared_ptr<SubtitleStream> s)
}
void
-FFmpegDecoder::filter_and_emit_video (AVFrame* frame)
+FFmpegDecoder::filter_and_emit_video ()
{
boost::mutex::scoped_lock lm (_filter_graphs_mutex);
shared_ptr<FilterGraph> graph;
list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin();
- while (i != _filter_graphs.end() && !(*i)->can_process (libdcp::Size (frame->width, frame->height), (AVPixelFormat) frame->format)) {
+ while (i != _filter_graphs.end() && !(*i)->can_process (libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)) {
++i;
}
if (i == _filter_graphs.end ()) {
- graph.reset (new FilterGraph (_film, this, libdcp::Size (frame->width, frame->height), (AVPixelFormat) frame->format));
+ graph.reset (new FilterGraph (_film, this, libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format));
_filter_graphs.push_back (graph);
- _film->log()->log (String::compose (N_("New graph for %1x%2, pixel format %3"), frame->width, frame->height, frame->format));
+ _film->log()->log (String::compose (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format));
} else {
graph = *i;
}
- list<shared_ptr<Image> > images = graph->process (frame);
+ list<shared_ptr<Image> > images = graph->process (_frame);
for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) {
- emit_video (*i, frame_time ());
+ emit_video (*i, av_frame_get_best_effort_timestamp (_frame) * av_q2d (_format_context->streams[_video_stream]->time_base));
}
}
@@ -614,53 +606,6 @@ FFmpegAudioStream::to_string () const
}
void
-FFmpegDecoder::out_with_sync ()
-{
- /* 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 (N_("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) {
- /* XXX: timestamp is wrong */
- repeat_last_video (source_pts_seconds);
- _film->log()->log (
- String::compose (
- N_("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 (N_("Frame removed at %1s"), out_pts_seconds));
- }
-}
-
-void
FFmpegDecoder::film_changed (Film::Property p)
{
switch (p) {
@@ -685,12 +630,6 @@ FFmpegDecoder::length () const
return (double(_format_context->duration) / AV_TIME_BASE) * frames_per_second();
}
-double
-FFmpegDecoder::frame_time () const
-{
- return av_frame_get_best_effort_timestamp(_frame) * av_q2d (_format_context->streams[_video_stream]->time_base);
-}
-
void
FFmpegDecoder::decode_audio_packet ()
{
@@ -707,54 +646,21 @@ FFmpegDecoder::decode_audio_packet ()
int frame_finished;
int const decode_result = avcodec_decode_audio4 (_audio_codec_context, _frame, &frame_finished, &copy_packet);
- if (decode_result >= 0 && frame_finished) {
-
- /* Where we are in the source, in seconds */
- double const source_pts_seconds = av_q2d (_format_context->streams[copy_packet.stream_index]->time_base)
- * av_frame_get_best_effort_timestamp(_frame);
-
- /* We only decode audio if we've had our first video packet through, and if it
- was before this packet. Until then audio is thrown away.
- */
+ if (decode_result >= 0) {
+ if (frame_finished) {
- if ((_first_video && _first_video.get() <= source_pts_seconds) || !_opt.decode_video) {
-
- if (!_first_audio && _opt.decode_video) {
- _first_audio = source_pts_seconds;
-
- /* This is our first audio frame, and if we've arrived here we must have had our
- first video frame. Push some silence to make up any gap between our first
- video frame and our first audio.
- */
-
- /* frames of silence that we must push */
- int const s = rint ((_first_audio.get() - _first_video.get()) * ffa->sample_rate ());
-
- _film->log()->log (
- String::compose (
- N_("First video at %1, first audio at %2, pushing %3 audio frames of silence for %4 channels (%5 bytes per sample)"),
- _first_video.get(), _first_audio.get(), s, ffa->channels(), bytes_per_audio_sample()
- )
- );
-
- if (s) {
- shared_ptr<AudioBuffers> audio (new AudioBuffers (ffa->channels(), s));
- audio->make_silent ();
- /* XXX: this time stamp is wrong */
- Audio (audio, source_pts_seconds);
- }
- }
+ /* Where we are in the source, in seconds */
+ double const source_pts_seconds = av_q2d (_format_context->streams[copy_packet.stream_index]->time_base)
+ * av_frame_get_best_effort_timestamp(_frame);
int const data_size = av_samples_get_buffer_size (
0, _audio_codec_context->channels, _frame->nb_samples, audio_sample_format (), 1
);
assert (_audio_codec_context->channels == _film->audio_channels());
- Audio (deinterleave_audio (_frame->data, data_size), source_pts_seconds );
+ Audio (deinterleave_audio (_frame->data, data_size), source_pts_seconds);
}
- }
-
- if (decode_result >= 0) {
+
copy_packet.data += decode_result;
copy_packet.size -= decode_result;
}