rendered paste bodyIndex: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.cpp (revision 23097)
+++ libs/libmythtv/NuppelVideoPlayer.cpp (working copy)
@@ -169,6 +169,8 @@
transcoding(false),
hasFullPositionMap(false), limitKeyRepeat(false),
errorMsg(QString::null), errorType(kError_None),
+ // Chapter stuff
+ jumpchapter(0),
// Bookmark stuff
bookmarkseek(0), previewFromBookmark(false),
// Seek
@@ -3248,6 +3250,12 @@
}
+void NuppelVideoPlayer::JumpChapter(int direction)
+{
+ if (jumpchapter == 0)
+ jumpchapter = direction;
+}
+
void NuppelVideoPlayer::SkipCommercials(int direction)
{
if (skipcommercials == 0)
@@ -3576,6 +3584,7 @@
}
rewindtime = fftime = 0;
+ jumpchapter = 0;
skipcommercials = 0;
if (bookmarkseek > 30)
@@ -3782,6 +3791,13 @@
RefreshPauseFrame();
need_change_dvd_track = 0;
}
+ //else if (jumpchapter != 0 && ffrew_skip == 1)
+ else if (jumpchapter != 0)
+ {
+ DoJumpChapter(jumpchapter);
+ RefreshPauseFrame();
+ jumpchapter = 0;
+ }
else if (player_ctx->tvchain && player_ctx->tvchain->NeedsToJump())
{
JumpToProgram();
@@ -3844,6 +3860,17 @@
need_change_dvd_track = 0;
}
+ if (jumpchapter != 0 && ffrew_skip == 1)
+ {
+ QMutexLocker locker(&internalPauseLock);
+
+ PauseVideo(true);
+ DoJumpChapter(jumpchapter);
+ UnpauseVideo(true);
+
+ jumpchapter = 0;
+ }
+
if (skipcommercials != 0 && ffrew_skip == 1)
{
QMutexLocker locker(&internalPauseLock);
@@ -6660,6 +6687,44 @@
}
}
+int NuppelVideoPlayer::GetNumChapters()
+{
+ return GetDecoder()->GetNumChapters();
+}
+
+bool NuppelVideoPlayer::DoJumpChapter(int direction)
+{
+ int desiredFrame;
+
+ if (direction == -1)
+ {
+ desiredFrame = GetDecoder()->GetPrevChapter(framesPlayed);
+ VERBOSE(VB_IMPORTANT, LOC +
+ QString("DoJumpChapter(desiredFrame %1)").arg(desiredFrame));
+ }
+ else
+ {
+ desiredFrame = GetDecoder()->GetNextChapter(framesPlayed);
+ VERBOSE(VB_IMPORTANT, LOC +
+ QString("DoJumpChapter(desiredFrame %1)").arg(desiredFrame));
+ }
+
+ if (paused && !editmode)
+ GetDecoder()->setExactSeeks(true);
+ if (direction == -1)
+ GetDecoder()->DoRewind(desiredFrame);
+ else
+ GetDecoder()->DoFastForward(desiredFrame);
+ GetDecoder()->setExactSeeks(exactseeks);
+
+ // Note: The video output will be reset by what the the decoder
+ // does, so we only need to reset the audio, subtitles, etc.
+ ClearAfterSeek(false);
+
+ lastSkipTime = time(NULL);
+ return true;
+}
+
bool NuppelVideoPlayer::DoSkipCommercials(int direction)
{
if (!hascommbreaktable)
Index: libs/libmythtv/decoderbase.h
===================================================================
--- libs/libmythtv/decoderbase.h (revision 23097)
+++ libs/libmythtv/decoderbase.h (working copy)
@@ -78,6 +78,9 @@
virtual bool GetFrame(int onlyvideo) = 0;
NuppelVideoPlayer *GetNVP() { return m_parent; }
+ virtual int GetNumChapters(void) { return 0; }
+ virtual int GetNextChapter(int framesPlayed) { return framesPlayed; }
+ virtual int GetPrevChapter(int framesPlayed) { return framesPlayed; }
virtual bool DoRewind(long long desiredFrame, bool doflush = true);
virtual bool DoFastForward(long long desiredFrame, bool doflush = true);
Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp (revision 23097)
+++ libs/libmythtv/avformatdecoder.cpp (working copy)
@@ -561,6 +561,61 @@
return ((lsb - base_ts)&mask);
}
+int AvFormatDecoder::GetNumChapters()
+{
+ return ic->nb_chapters;
+}
+
+int AvFormatDecoder::GetPrevChapter(int framesPlayed)
+{
+ int framenum;
+ int prevframenum = framesPlayed;
+ int prevchapter = 0;
+ for (int i=0; i < ic->nb_chapters; i++)
+ {
+ int num = ic->chapters[i]->time_base.num;
+ int den = ic->chapters[i]->time_base.den;
+ int64_t start = ic->chapters[i]->start;
+ int64_t end = ic->chapters[i]->end;
+ double total_secs = (double)((long double)start * (long double)num / (long double)den);
+ framenum = (int)(total_secs * fps);
+ VERBOSE(VB_IMPORTANT, LOC +
+ QString("GetPrevChapter(fps %1 secs %2 framesPlayed %3 %4)").arg(fps).arg(total_secs).arg(framesPlayed).arg(framenum));
+ if (framenum > (framesPlayed - (int)fps))
+ {
+ VERBOSE(VB_IMPORTANT, LOC +
+ QString("GetPrevChapter(selected chapter %1 framenum %2)").arg(prevchapter).arg(prevframenum));
+ return prevframenum;
+ }
+ prevframenum = framenum;
+ prevchapter = i;
+ }
+ return framenum;
+}
+
+int AvFormatDecoder::GetNextChapter(int framesPlayed)
+{
+ int framenum;
+ for (int i=0; i < ic->nb_chapters; i++)
+ {
+ int num = ic->chapters[i]->time_base.num;
+ int den = ic->chapters[i]->time_base.den;
+ int64_t start = ic->chapters[i]->start;
+ int64_t end = ic->chapters[i]->end;
+ double total_secs = (double)((long double)start * (long double)num / (long double)den);
+ framenum = (int)(total_secs * fps);
+ VERBOSE(VB_IMPORTANT, LOC +
+ QString("GetNextChapter(fps %1 secs %2 framesPlayed %3 %4)").arg(fps).arg(total_secs).arg(framesPlayed).arg(framenum));
+ if (framenum > framesPlayed)
+ {
+ VERBOSE(VB_IMPORTANT, LOC +
+ QString("GetNextChapter(selected chapter %1 framenum %2)").arg(i).arg(framenum));
+ return framenum;
+ }
+ }
+ return framesPlayed;
+}
+
bool AvFormatDecoder::DoRewind(long long desiredFrame, bool discardFrames)
{
VERBOSE(VB_PLAYBACK, LOC + "DoRewind("
@@ -1080,6 +1135,25 @@
QString("Successfully opened decoder for file: "
"\"%1\". novideo(%2)").arg(filename).arg(novideo));
+ // Print AVContext chapter information
+ for (int i=0; i < ic->nb_chapters; i++)
+ {
+ int id = ic->chapters[i]->id;
+ int num = ic->chapters[i]->time_base.num;
+ int den = ic->chapters[i]->time_base.den;
+ int64_t start = ic->chapters[i]->start;
+ int64_t end = ic->chapters[i]->end;
+ double total_secs = (double)((long double)start * (long double)num / (long double)den);
+ int hours = (int)total_secs / 60 / 60;
+ int minutes = ((int)total_secs / 60) - (hours * 60);
+ double secs = total_secs - (double)(hours * 60 *60) - (double)(minutes * 60);
+ VERBOSE(VB_PLAYBACK, LOC + QString("Chapter %1 found %2:%3:%4%5")
+ .arg(QString().sprintf("%02d", i))
+ .arg(QString().sprintf("%02d", hours))
+ .arg(QString().sprintf("%02d", minutes))
+ .arg(QString().sprintf("%02.3f", secs)));
+ }
+
// Return true if recording has position map
return recordingHasPositionMap;
}
Index: libs/libmythtv/tv_play.h
===================================================================
--- libs/libmythtv/tv_play.h (revision 23097)
+++ libs/libmythtv/tv_play.h (working copy)
@@ -436,6 +436,8 @@
float StopFFRew(PlayerContext*);
void ChangeFFRew(PlayerContext*, int direction);
void SetFFRew(PlayerContext*, int index);
+ int GetNumChapters(PlayerContext*);
+ void DoJumpChapter(PlayerContext*, int direction);
void DoSkipCommercials(PlayerContext*, int direction);
void StartProgramEditMode(PlayerContext*);
Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.h (revision 23097)
+++ libs/libmythtv/NuppelVideoPlayer.h (working copy)
@@ -265,6 +265,9 @@
bool RebuildSeekTable(bool showPercentage = true, StatusCallback cb = NULL,
void* cbData = NULL);
+ // Chapter stuff
+ void JumpChapter(int direction);
+
// Commercial stuff
void SkipCommercials(int direction);
int FlagCommercials(bool showPercentage, bool fullSpeed,
@@ -409,6 +412,8 @@
void CheckTVChain();
void FileChangedCallback();
+ // Chapter public stuff
+ int GetNumChapters();
// DVD public stuff
void ChangeDVDTrack(bool ffw);
void ActivateDVDButton(void);
@@ -486,6 +491,9 @@
void JumpToNetFrame(long long net) { JumpToFrame(framesPlayed + net); }
void RefreshPauseFrame(void);
+ // Private chapter jumping
+ bool DoJumpChapter(int direction);
+
// Private commercial skipping
void SkipCommercialsByBlanks(void);
bool DoSkipCommercials(int direction);
@@ -596,6 +604,9 @@
mutable QString errorMsg; ///< Reason why NVP exited with a error
mutable int errorType;
+ // Chapter stuff
+ int jumpchapter;
+
// Bookmark stuff
long long bookmarkseek;
bool previewFromBookmark;
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp (revision 23097)
+++ libs/libmythtv/tv_play.cpp (working copy)
@@ -4082,9 +4082,15 @@
bool handled = true;
if (has_action("SKIPCOMMERCIAL", actions) && !isDVD)
- DoSkipCommercials(ctx, 1);
+ if (GetNumChapters(ctx) > 0)
+ DoJumpChapter(ctx, 1);
+ else
+ DoSkipCommercials(ctx, 1);
else if (has_action("SKIPCOMMBACK", actions) && !isDVD)
- DoSkipCommercials(ctx, -1);
+ if (GetNumChapters(ctx) > 0)
+ DoJumpChapter(ctx, -1);
+ else
+ DoSkipCommercials(ctx, -1);
else if (has_action("QUEUETRANSCODE", actions) && !isDVD)
DoQueueTranscode(ctx, "Default");
else if (has_action("QUEUETRANSCODE_AUTO", actions) && !isDVD)
@@ -6106,6 +6112,52 @@
ctx->UnlockPlayingInfo(__FILE__, __LINE__);
}
+int TV::GetNumChapters(PlayerContext *ctx)
+{
+ int num_chapters;
+ ctx->LockDeleteNVP(__FILE__, __LINE__);
+ if (ctx->nvp)
+ num_chapters = ctx->nvp->GetNumChapters();
+ ctx->UnlockDeleteNVP(__FILE__, __LINE__);
+
+ return num_chapters;
+}
+
+void TV::DoJumpChapter(PlayerContext *ctx, int direction)
+{
+ NormalSpeed(ctx);
+ StopFFRew(ctx);
+
+ ctx->LockDeleteNVP(__FILE__, __LINE__);
+ bool muted = MuteChannelChange(ctx);
+ ctx->UnlockDeleteNVP(__FILE__, __LINE__);
+
+ struct StatusPosInfo posInfo;
+ ctx->CalcNVPSliderPosition(posInfo);
+
+ bool slidertype = false;
+
+ OSD *osd = GetOSDLock(ctx);
+ if (osd)
+ {
+ posInfo.desc = tr("Searching...");
+ if (direction < 0)
+ osd->ShowStatus(posInfo, slidertype, tr("Previous Chapter"), 6);
+ else
+ osd->ShowStatus(posInfo, slidertype, tr("Next Chapter"), 6);
+ SetUpdateOSDPosition(true);
+ }
+ ReturnOSDLock(ctx, osd);
+
+ ctx->LockDeleteNVP(__FILE__, __LINE__);
+ if (ctx->nvp)
+ ctx->nvp->JumpChapter(direction);
+ ctx->UnlockDeleteNVP(__FILE__, __LINE__);
+
+ if (muted)
+ SetMuteTimer(ctx, kMuteTimeout);
+}
+
void TV::DoSkipCommercials(PlayerContext *ctx, int direction)
{
NormalSpeed(ctx);
Index: libs/libmythtv/avformatdecoder.h
===================================================================
--- libs/libmythtv/avformatdecoder.h (revision 23097)
+++ libs/libmythtv/avformatdecoder.h (working copy)
@@ -131,6 +131,9 @@
int ScanStreams(bool novideo);
+ virtual int GetNumChapters();
+ virtual int GetPrevChapter(int framesPlayed);
+ virtual int GetNextChapter(int framesPlayed);
virtual bool DoRewind(long long desiredFrame, bool doflush = true);
virtual bool DoFastForward(long long desiredFrame, bool doflush = true);