X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_examiner.cc;h=2e48810b1ed87779a9bd6e5f53d1df5931cc4a89;hb=5a5324ed3a381a86dfe0a6e3932c1d58fdcd596f;hp=64866047863afc9de6b9f9893609d84958e4c723;hpb=0e9cc320b18ae53e2bf0cc8fdb9984b58e33e0ec;p=dcpomatic.git diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc index 648660478..2e48810b1 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -1,19 +1,20 @@ /* Copyright (C) 2013-2015 Carl Hetherington - This program is free software; you can redistribute it and/or modify + This file is part of DCP-o-matic. + + DCP-o-matic 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, + DCP-o-matic 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. + along with DCP-o-matic. If not, see . */ @@ -31,6 +32,7 @@ extern "C" { #include "util.h" #include "safe_stringstream.h" #include +#include #include #include "i18n.h" @@ -39,6 +41,7 @@ using std::string; using std::cout; using std::max; using boost::shared_ptr; +using boost::make_shared; using boost::optional; /** @param job job that the examiner is operating in, or 0 */ @@ -61,28 +64,43 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptrcodec->channel_layout = av_get_default_channel_layout (s->codec->channels); } + DCPOMATIC_ASSERT (_format_context->duration != AV_NOPTS_VALUE); + DCPOMATIC_ASSERT (s->codec->codec); + DCPOMATIC_ASSERT (s->codec->codec->name); + _audio_streams.push_back ( shared_ptr ( - new FFmpegAudioStream (audio_stream_name (s), s->id, s->codec->sample_rate, s->codec->channels) + new FFmpegAudioStream ( + stream_name (s), + s->codec->codec->name, + s->id, + s->codec->sample_rate, + (double (_format_context->duration) / AV_TIME_BASE) * s->codec->sample_rate, + s->codec->channels + ) ) ); } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { - _subtitle_streams.push_back (shared_ptr (new FFmpegSubtitleStream (subtitle_stream_name (s), s->id))); + _subtitle_streams.push_back (boost::make_shared (subtitle_stream_name (s), s->id)); } } - /* See if the header has duration information in it */ - _need_video_length = _format_context->duration == AV_NOPTS_VALUE; - if (!_need_video_length) { - _video_length = (double (_format_context->duration) / AV_TIME_BASE) * video_frame_rate().get (); + if (has_video ()) { + /* See if the header has duration information in it */ + _need_video_length = _format_context->duration == AV_NOPTS_VALUE; + if (!_need_video_length) { + _video_length = (double (_format_context->duration) / AV_TIME_BASE) * video_frame_rate().get (); + } } if (job) { if (_need_video_length) { job->sub (_("Finding length and subtitles")); - } else { + } else if (!_subtitle_streams.empty()) { job->sub (_("Finding subtitles")); + } else { + job->sub (_("Finding length")); } } @@ -113,7 +131,7 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptrstreams[_packet.stream_index]->codec; - if (_packet.stream_index == _video_stream) { + if (_video_stream && _packet.stream_index == _video_stream.get()) { video_packet (context); } @@ -169,7 +187,7 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptr i, _subtitle_streams) { i->add_offset (pts_offset (_audio_streams, _first_video, video_frame_rate().get())); } @@ -179,6 +197,8 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptr= 0 && frame_finished) { if (!_first_video) { - _first_video = frame_time (_format_context->streams[_video_stream]); + _first_video = frame_time (_format_context->streams[_video_stream.get()]); } if (_need_video_length) { _video_length = frame_time ( - _format_context->streams[_video_stream] + _format_context->streams[_video_stream.get()] ).get_value_or (ContentTime ()).frames_round (video_frame_rate().get ()); } } @@ -249,6 +269,19 @@ FFmpegExaminer::subtitle_packet (AVCodecContext* context, shared_ptrtype == SUBTITLE_BITMAP) { +#ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT + uint32_t* palette = (uint32_t *) sub.rects[i]->pict.data[1]; + for (int j = 0; j < sub.rects[i]->nb_colors; ++j) { + RGBA rgba ( + (palette[j] & 0x00ff0000) >> 16, + (palette[j] & 0x0000ff00) >> 8, + (palette[j] & 0x000000ff) >> 0, + (palette[j] & 0xff000000) >> 24 + ); + + stream->set_colour (rgba, rgba); + } +#else uint32_t* palette = (uint32_t *) sub.rects[i]->data[1]; for (int j = 0; j < sub.rects[i]->nb_colors; ++j) { RGBA rgba ( @@ -260,6 +293,7 @@ FFmpegExaminer::subtitle_packet (AVCodecContext* context, shared_ptrset_colour (rgba, rgba); } +#endif } } @@ -283,11 +317,12 @@ FFmpegExaminer::frame_time (AVStream* s) const optional FFmpegExaminer::video_frame_rate () const { + DCPOMATIC_ASSERT (_video_stream); /* This use of r_frame_rate is debateable; there's a few different * frame rates in the format context, but this one seems to be the most * reliable. */ - return av_q2d (av_stream_get_r_frame_rate (_format_context->streams[_video_stream])); + return av_q2d (av_stream_get_r_frame_rate (_format_context->streams[_video_stream.get()])); } dcp::Size @@ -306,7 +341,8 @@ FFmpegExaminer::video_length () const optional FFmpegExaminer::sample_aspect_ratio () const { - AVRational sar = av_guess_sample_aspect_ratio (_format_context, _format_context->streams[_video_stream], 0); + DCPOMATIC_ASSERT (_video_stream); + AVRational sar = av_guess_sample_aspect_ratio (_format_context, _format_context->streams[_video_stream.get()], 0); if (sar.num == 0) { /* I assume this means that we don't know */ return optional (); @@ -314,22 +350,6 @@ FFmpegExaminer::sample_aspect_ratio () const return double (sar.num) / sar.den; } -string -FFmpegExaminer::audio_stream_name (AVStream* s) const -{ - SafeStringStream n; - - n << stream_name (s); - - if (!n.str().empty()) { - n << "; "; - } - - n << s->codec->channels << " channels"; - - return n.str (); -} - string FFmpegExaminer::subtitle_stream_name (AVStream* s) const { @@ -459,3 +479,9 @@ FFmpegExaminer::yuv () const return false; } } + +bool +FFmpegExaminer::has_video () const +{ + return static_cast (_video_stream); +}