extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
+#include <libavutil/pixfmt.h>
+#include <libavutil/pixdesc.h>
}
#include "ffmpeg_examiner.h"
#include "ffmpeg_content.h"
#include "ffmpeg_subtitle_stream.h"
#include "util.h"
#include "safe_stringstream.h"
+#include <iostream>
#include "i18n.h"
if (s->codec->channel_layout == 0) {
s->codec->channel_layout = av_get_default_channel_layout (s->codec->channels);
}
-
+
_audio_streams.push_back (
shared_ptr<FFmpegAudioStream> (
new FFmpegAudioStream (audio_stream_name (s), s->id, s->codec->sample_rate, s->codec->channels)
job->set_progress_unknown ();
}
+ if (job) {
+ job->sub (_("Finding subtitles"));
+ }
+
/* Run through until we find:
* - the first video.
* - the first audio for each stream.
* where we should look for subtitles (video and audio are always present,
* so they are ok).
*/
+
while (true) {
int r = av_read_frame (_format_context, &_packet);
if (r < 0) {
break;
}
+ if (job) {
+ job->set_progress_unknown ();
+ }
+
AVCodecContext* context = _format_context->streams[_packet.stream_index]->codec;
if (_packet.stream_index == _video_stream) {
video_packet (context);
}
-
+
+ bool got_all_audio = true;
+
for (size_t i = 0; i < _audio_streams.size(); ++i) {
if (_audio_streams[i]->uses_index (_format_context, _packet.stream_index)) {
audio_packet (context, _audio_streams[i]);
}
+ if (!_audio_streams[i]->first_audio) {
+ got_all_audio = false;
+ }
}
for (size_t i = 0; i < _subtitle_streams.size(); ++i) {
}
av_free_packet (&_packet);
+
+ if (_first_video && got_all_audio && _subtitle_streams.empty ()) {
+ /* All done */
+ break;
+ }
}
}
if (_need_video_length) {
_video_length = frame_time (
_format_context->streams[_video_stream]
- ).get_value_or (ContentTime ()).frames (video_frame_rate().get ());
+ ).get_value_or (ContentTime ()).frames_round (video_frame_rate().get ());
}
}
}
FFmpegExaminer::frame_time (AVStream* s) const
{
optional<ContentTime> t;
-
+
int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
if (bet != AV_NOPTS_VALUE) {
t = ContentTime::from_seconds (bet * av_q2d (s->time_base));
return t;
}
-optional<float>
+optional<double>
FFmpegExaminer::video_frame_rate () const
{
/* This use of r_frame_rate is debateable; there's a few different
return max (Frame (1), _video_length);
}
-optional<float>
+optional<double>
FFmpegExaminer::sample_aspect_ratio () const
{
AVRational sar = av_guess_sample_aspect_ratio (_format_context, _format_context->streams[_video_stream], 0);
if (sar.num == 0) {
/* I assume this means that we don't know */
- return optional<float> ();
+ return optional<double> ();
}
- return float (sar.num) / sar.den;
+ return double (sar.num) / sar.den;
}
string
if (lang) {
n << lang->value;
}
-
+
AVDictionaryEntry const * title = av_dict_get (s->metadata, "title", 0, 0);
if (title) {
if (!n.str().empty()) {
return n.str ();
}
+
+int
+FFmpegExaminer::bits_per_pixel () const
+{
+ return av_get_bits_per_pixel (av_pix_fmt_desc_get (video_codec_context()->pix_fmt));
+}