diff --git a/app/decoder/ffmpeg/ffmpegdecoder.cpp b/app/decoder/ffmpeg/ffmpegdecoder.cpp index c7b437df5..84f2ecbce 100644 --- a/app/decoder/ffmpeg/ffmpegdecoder.cpp +++ b/app/decoder/ffmpeg/ffmpegdecoder.cpp @@ -363,8 +363,6 @@ bool FFmpegDecoder::Probe(Footage *f) // Retrieve metadata about the media av_dump_format(fmt_ctx_, 0, filename, 0); - qDebug() << "Format duration:" << fmt_ctx_->duration; - // Dump it into the Footage object for (unsigned int i=0;inb_streams;i++) { @@ -379,6 +377,7 @@ bool FFmpegDecoder::Probe(Footage *f) video_stream->set_width(avstream_->codecpar->width); video_stream->set_height(avstream_->codecpar->height); + video_stream->set_frame_rate(av_guess_frame_rate(fmt_ctx_, avstream_, nullptr)); str = video_stream; diff --git a/app/project/item/footage/footage.cpp b/app/project/item/footage/footage.cpp index 8bfee24f5..6806e366c 100644 --- a/app/project/item/footage/footage.cpp +++ b/app/project/item/footage/footage.cpp @@ -22,6 +22,7 @@ #include +#include "common/timecodefunctions.h" #include "ui/icons/icons.h" Footage::Footage() @@ -146,6 +147,60 @@ QIcon Footage::icon() return QIcon(); } +#include +QString Footage::duration() +{ + if (streams_.isEmpty()) { + return QString(); + } + + if (streams_.first()->type() == Stream::kVideo) { + VideoStreamPtr video_stream = std::static_pointer_cast(streams_.first()); + + int64_t duration = video_stream->duration(); + rational frame_rate_timebase = video_stream->frame_rate().flipped(); + + if (video_stream->timebase() != frame_rate_timebase) { + // Convert from timebase to frame rate + rational duration_time = olive::timestamp_to_time(duration, video_stream->timebase()); + duration = olive::time_to_timestamp(duration_time, frame_rate_timebase); + } + + return olive::timestamp_to_timecode(duration, + frame_rate_timebase, + olive::CurrentTimecodeDisplay()); + } else if (streams_.first()->type() == Stream::kAudio) { + AudioStreamPtr audio_stream = std::static_pointer_cast(streams_.first()); + + return olive::timestamp_to_timecode(streams_.first()->duration(), + streams_.first()->timebase(), + olive::CurrentTimecodeDisplay()); + } + + return QString(); +} + +QString Footage::rate() +{ + if (streams_.isEmpty()) { + return QString(); + } + + if (streams_.first()->type() == Stream::kVideo) { + // Return the timebase as a frame rate + VideoStreamPtr video_stream = std::static_pointer_cast(streams_.first()); + + return QCoreApplication::translate("Footage", "%1 FPS").arg(video_stream->frame_rate().toDouble()); + } else if (streams_.first()->type() == Stream::kAudio) { + // Return the sample rate + AudioStreamPtr audio_stream = std::static_pointer_cast(streams_.first()); + + return QCoreApplication::translate("Footage", "%1 Hz").arg(audio_stream->sample_rate()); + } + + return olive::timestamp_to_timecode(streams_.first()->duration(), streams_.first()->timebase(), olive::CurrentTimecodeDisplay()); +} + void Footage::ClearStreams() { if (streams_.empty()) { diff --git a/app/project/item/footage/footage.h b/app/project/item/footage/footage.h index 130aaa2d3..53775a467 100644 --- a/app/project/item/footage/footage.h +++ b/app/project/item/footage/footage.h @@ -207,6 +207,10 @@ public: virtual QIcon icon() override; + virtual QString duration() override; + + virtual QString rate() override; + private: /** * @brief Internal function to delete all Stream children and empty the array diff --git a/app/project/item/footage/videostream.cpp b/app/project/item/footage/videostream.cpp index d38eac54f..ed97bb94d 100644 --- a/app/project/item/footage/videostream.cpp +++ b/app/project/item/footage/videostream.cpp @@ -31,3 +31,13 @@ QString VideoStream::description() QString::number(width()), QString::number(height())); } + +const rational &VideoStream::frame_rate() +{ + return frame_rate_; +} + +void VideoStream::set_frame_rate(const rational &frame_rate) +{ + frame_rate_ = frame_rate; +} diff --git a/app/project/item/footage/videostream.h b/app/project/item/footage/videostream.h index 1f01415be..94c66c5c8 100644 --- a/app/project/item/footage/videostream.h +++ b/app/project/item/footage/videostream.h @@ -29,6 +29,17 @@ public: VideoStream(); virtual QString description() override; + + /** + * @brief Get this video stream's frame rate + * + * Used purely for metadata, rendering uses the timebase instead. + */ + const rational& frame_rate(); + void set_frame_rate(const rational& frame_rate); + +private: + rational frame_rate_; }; using VideoStreamPtr = std::shared_ptr; diff --git a/app/project/item/item.cpp b/app/project/item/item.cpp index d930b2b3b..d7ad5b767 100644 --- a/app/project/item/item.cpp +++ b/app/project/item/item.cpp @@ -101,6 +101,16 @@ void Item::set_tooltip(const QString &t) tooltip_ = t; } +QString Item::duration() +{ + return QString(); +} + +QString Item::rate() +{ + return QString(); +} + Item *Item::parent() const { return parent_; diff --git a/app/project/item/item.h b/app/project/item/item.h index 2fa065792..bb13ef87a 100644 --- a/app/project/item/item.h +++ b/app/project/item/item.h @@ -94,6 +94,10 @@ public: virtual QIcon icon() = 0; + virtual QString duration(); + + virtual QString rate(); + Item *parent() const; const Item* root() const; diff --git a/app/project/item/sequence/sequence.cpp b/app/project/item/sequence/sequence.cpp index ad14e04e0..13f7a86cc 100644 --- a/app/project/item/sequence/sequence.cpp +++ b/app/project/item/sequence/sequence.cpp @@ -20,6 +20,8 @@ #include "sequence.h" +#include + #include "common/channellayout.h" #include "ui/icons/icons.h" @@ -37,6 +39,11 @@ QIcon Sequence::icon() return olive::icon::Sequence; } +QString Sequence::rate() +{ + return QCoreApplication::translate("Sequence", "%1 FPS").arg(video_time_base_.flipped().toDouble()); +} + const int &Sequence::video_width() { return video_width_; diff --git a/app/project/item/sequence/sequence.h b/app/project/item/sequence/sequence.h index 77a7f1681..16cd44622 100644 --- a/app/project/item/sequence/sequence.h +++ b/app/project/item/sequence/sequence.h @@ -40,6 +40,8 @@ public: virtual QIcon icon() override; + virtual QString rate() override; + /* VIDEO GETTER/SETTER FUNCTIONS */ const int& video_width(); diff --git a/app/project/projectviewmodel.cpp b/app/project/projectviewmodel.cpp index c89841512..8c6dee3b2 100644 --- a/app/project/projectviewmodel.cpp +++ b/app/project/projectviewmodel.cpp @@ -131,11 +131,9 @@ QVariant ProjectViewModel::data(const QModelIndex &index, int role) const case kName: return internal_item->name(); case kDuration: - // FIXME Return actual information - return "00:00:00;00"; + return internal_item->duration(); case kRate: - // FIXME Return actual information - return "29.97 FPS"; + return internal_item->rate(); } } break;