Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Store calculated duration in the db

At recording end, a value of recendts - recstartts (converted to ms) is stored
in the recordedmarkup table.  At the end of commflag or a seektable rebuild,
the accurate number of ms (as determined by adding frame times during playback)
will overwrite this value.

On playback, this value is checked first.  If the value is in the database, it
is used for the duration in the OSD.  If it is not there, then the duration
from ffmpeg will be used instead.

To get this working, it was necessary to reset the calculated duration after
the logo scan in commflagging, otherwise the end result was incorrect.
  • Loading branch information...
commit 53663999b09a4f7c4a3b67edf2dcdf08f170d761 1 parent 46e694c
@Beirdo Beirdo authored
View
43 mythtv/libs/libmyth/programinfo.cpp
@@ -3327,6 +3327,39 @@ void ProgramInfo::SaveFrameRate(uint64_t frame, uint framerate)
}
+/// \brief Store the Total Duration at frame 0 in the recordedmarkup table
+void ProgramInfo::SaveTotalDuration(int64_t duration)
+{
+ if (!IsRecording())
+ return;
+
+ MSqlQuery query(MSqlQuery::InitCon());
+
+ query.prepare("DELETE FROM recordedmarkup "
+ " WHERE chanid=:CHANID "
+ " AND starttime=:STARTTIME "
+ " AND type=:TYPE");
+ query.bindValue(":CHANID", chanid);
+ query.bindValue(":STARTTIME", recstartts);
+ query.bindValue(":TYPE", MARK_DURATION_MS);
+
+ if (!query.exec())
+ MythDB::DBError("Duration delete", query);
+
+ query.prepare("INSERT INTO recordedmarkup"
+ " (chanid, starttime, mark, type, data)"
+ " VALUES"
+ " ( :CHANID, :STARTTIME, 0, :TYPE, :DATA);");
+ query.bindValue(":CHANID", chanid);
+ query.bindValue(":STARTTIME", recstartts);
+ query.bindValue(":TYPE", MARK_DURATION_MS);
+ query.bindValue(":DATA", (uint)(duration / 1000));
+
+ if (!query.exec())
+ MythDB::DBError("Duration insert", query);
+}
+
+
/// \brief Store the Resolution at frame in the recordedmarkup table
/// \note All frames until the next one with a stored resolution
/// are assumed to have the same resolution
@@ -3426,6 +3459,16 @@ uint ProgramInfo::QueryAverageFrameRate(void) const
return load_markup_datum(MARK_VIDEO_RATE, chanid, recstartts);
}
+/** \brief If present in recording this loads total duration of the
+ * main video stream from database's stream markup table.
+ */
+int64_t ProgramInfo::QueryTotalDuration(void) const
+{
+ int64_t msec = load_markup_datum(MARK_DURATION_MS, chanid, recstartts);
+ return msec * 1000;
+}
+
+
void ProgramInfo::SaveResolutionProperty(VideoProperty vid_flags)
{
MSqlQuery query(MSqlQuery::InitCon());
View
2  mythtv/libs/libmyth/programinfo.h
@@ -500,6 +500,7 @@ class MPUBLIC ProgramInfo
uint QueryAverageWidth(void) const;
uint QueryAverageHeight(void) const;
uint QueryAverageFrameRate(void) const;
+ int64_t QueryTotalDuration(void) const;
QString QueryRecordingGroup(void) const;
bool QueryMarkupFlag(MarkTypes type) const;
uint QueryTranscoderID(void) const;
@@ -521,6 +522,7 @@ class MPUBLIC ProgramInfo
void SaveAspect(uint64_t frame, MarkTypes type, uint customAspect);
void SaveResolution(uint64_t frame, uint width, uint height);
void SaveFrameRate(uint64_t frame, uint framerate);
+ void SaveTotalDuration(int64_t duration);
void SaveResolutionProperty(VideoProperty vid_flags);
void SaveMarkupFlag(MarkTypes type) const;
void ClearMarkupFlag(MarkTypes type) const { ClearMarkupMap(type); }
View
1  mythtv/libs/libmyth/programtypes.h
@@ -62,6 +62,7 @@ typedef enum {
MARK_VIDEO_WIDTH = 30,
MARK_VIDEO_HEIGHT = 31,
MARK_VIDEO_RATE = 32,
+ MARK_DURATION_MS = 33,
} MarkTypes;
MPUBLIC QString toString(MarkTypes type);
View
17 mythtv/libs/libmythtv/avformatdecoder.cpp
@@ -990,8 +990,21 @@ int AvFormatDecoder::OpenFile(RingBuffer *rbuffer, bool novideo,
}
}
- // If watching pre-recorded television or video use ffmpeg duration
- int64_t dur = ic->duration / (int64_t)AV_TIME_BASE;
+ // If watching pre-recorded television or video use the marked duration
+ // from the db if it exists, else ffmpeg duration
+ int64_t dur = 0;
+
+ if (m_playbackinfo)
+ {
+ dur = m_playbackinfo->QueryTotalDuration();
+ dur /= 1000000;
+ }
+
+ if (dur == 0)
+ {
+ dur = ic->duration / (int64_t)AV_TIME_BASE;
+ }
+
if (dur > 0 && !livetv && !watchingrecording)
{
m_parent->SetDuration((int)dur);
View
8 mythtv/libs/libmythtv/decoderbase.cpp
@@ -1171,4 +1171,12 @@ int to_track_type(const QString &str)
return ret;
}
+void DecoderBase::SaveTotalDuration(void)
+{
+ if (!m_playbackinfo || !totalDuration)
+ return;
+
+ m_playbackinfo->SaveTotalDuration(totalDuration);
+}
+
/* vim: set expandtab tabstop=4 shiftwidth=4: */
View
3  mythtv/libs/libmythtv/decoderbase.h
@@ -198,6 +198,9 @@ class DecoderBase
virtual bool SetAudioByComponentTag(int) { return false; }
virtual bool SetVideoByComponentTag(int) { return false; }
+ void SaveTotalDuration(void);
+ void ResetTotalDuration(void) { totalDuration = 0; }
+
protected:
virtual int AutoSelectTrack(uint type);
inline void AutoSelectTracks(void);
View
2  mythtv/libs/libmythtv/mythcommflagplayer.cpp
@@ -178,6 +178,8 @@ bool MythCommFlagPlayer::RebuildSeekTable(
fflush( stdout );
}
+ SaveTotalDuration();
+
SetPlaying(false);
killdecoder = true;
View
16 mythtv/libs/libmythtv/mythplayer.cpp
@@ -4679,6 +4679,22 @@ void MythPlayer::SetOSDStatus(const QString &title, OSDTimeout timeout)
osd->SetValues("osd_status", info.values, timeout);
}
+void MythPlayer::SaveTotalDuration(void)
+{
+ if (!decoder)
+ return;
+
+ decoder->SaveTotalDuration();
+}
+
+void MythPlayer::ResetTotalDuration(void)
+{
+ if (!decoder)
+ return;
+
+ decoder->ResetTotalDuration();
+}
+
static unsigned dbg_ident(const MythPlayer *player)
{
static QMutex dbg_lock;
View
3  mythtv/libs/libmythtv/mythplayer.h
@@ -291,6 +291,9 @@ class MPUBLIC MythPlayer
// Public picture controls
void ToggleStudioLevels(void);
+ void SaveTotalDuration(void);
+ void ResetTotalDuration(void);
+
protected:
// Initialization
void OpenDummy(void);
View
7 mythtv/libs/libmythtv/recorderbase.cpp
@@ -376,5 +376,12 @@ void RecorderBase::FrameRateChange(uint framerate, long long frame)
curRecording->SaveFrameRate(frame, framerate);
}
+void RecorderBase::SetDuration(uint64_t duration)
+{
+ if (curRecording)
+ curRecording->SaveTotalDuration(duration);
+}
+
+
/* vim: set expandtab tabstop=4 shiftwidth=4: */
View
4 mythtv/libs/libmythtv/recorderbase.h
@@ -257,6 +257,10 @@ class MPUBLIC RecorderBase
*/
void FrameRateChange(uint framerate, long long frame);
+ /** \brief Note the total duration in the recordedmark table
+ */
+ void SetDuration(uint64_t duration);
+
TVRec *tvrec;
RingBuffer *ringBuffer;
bool weMadeBuffer;
View
5 mythtv/libs/libmythtv/recordinginfo.cpp
@@ -1057,6 +1057,11 @@ void RecordingInfo::FinishedRecording(bool prematurestop)
{
recstatus = rsRecorded;
+ uint starttime = recstartts.toTime_t();
+ uint endtime = recendts.toTime_t();
+ int64_t duration = ((int64_t)endtime - (int64_t)starttime) * 1000000;
+ SaveTotalDuration(duration);
+
QString msg = "Finished recording";
QString msg_subtitle = subtitle.isEmpty() ? "" :
QString(" \"%1\"").arg(subtitle);
View
2  mythtv/programs/mythcommflag/ClassicCommDetector.cpp
@@ -397,6 +397,8 @@ bool ClassicCommDetector::go()
emit breathe();
+ player->ResetTotalDuration();
+
while (!player->GetEof())
{
struct timeval startTime;
View
7 mythtv/programs/mythcommflag/CommDetector2.cpp
@@ -599,6 +599,8 @@ bool CommDetector2::go(void)
QTime passTime, clock;
struct timeval getframetime;
+ player->ResetTotalDuration();
+
if (searchingForLogo(logoFinder, *currentPass))
emit statusUpdate(QObject::tr("Performing Logo Identification"));
@@ -716,6 +718,11 @@ bool CommDetector2::go(void)
player->DiscardVideoFrame(currentFrame);
}
+ // Save total duration only on the last pass, which hopefully does
+ // no skipping.
+ if (passno + 1 == npasses)
+ player->SaveTotalDuration();
+
currentPass->insert(currentPass->end(),
finishedAnalyzers.begin(),
finishedAnalyzers.end());
View
2  mythtv/programs/mythcommflag/main.cpp
@@ -627,6 +627,8 @@ static int DoFlagCommercials(
if (result)
{
+ cfp->SaveTotalDuration();
+
frm_dir_map_t commBreakList;
commDetector->GetCommercialBreakList(commBreakList);
comms_found = commBreakList.size() / 2;
Please sign in to comment.
Something went wrong with that request. Please try again.