commit 50ca6e464e1a239c113b738cc6dd72c1c2a11689
Author: Mark Spieth <mspieth@digivation.com.au>
Date: Wed Jan 5 10:51:51 2011 +1100
play media to end when eof detected
diff --git a/mythtv/libs/libmythtv/decoderbase.cpp b/mythtv/libs/libmythtv/decoderbase.cpp
index 0f5c2e6..a397c59 100644
a
|
b
|
DecoderBase::DecoderBase(MythPlayer *parent, const ProgramInfo &pginfo) |
30 | 30 | framesPlayed(0), framesRead(0), totalDuration(0), |
31 | 31 | lastKey(0), keyframedist(-1), indexOffset(0), |
32 | 32 | |
33 | | ateof(false), exitafterdecoded(false), transcoding(false), |
| 33 | ateof(kEofStateNone), exitafterdecoded(false), transcoding(false), |
34 | 34 | |
35 | 35 | hasFullPositionMap(false), recordingHasPositionMap(false), |
36 | 36 | posmapStarted(false), positionMapType(MARK_UNSET), |
… |
… |
void DecoderBase::Reset(bool reset_video_data, bool seek_reset, bool reset_file) |
91 | 91 | if (reset_file) |
92 | 92 | { |
93 | 93 | waitingForChange = false; |
94 | | SetEof(false); |
| 94 | SetEof(kEofStateNone); |
95 | 95 | } |
96 | 96 | } |
97 | 97 | |
diff --git a/mythtv/libs/libmythtv/decoderbase.h b/mythtv/libs/libmythtv/decoderbase.h
index 7fb5f43..84a2c53 100644
a
|
b
|
typedef enum AudioTrackType |
59 | 59 | } AudioTrackType; |
60 | 60 | QString toString(AudioTrackType type); |
61 | 61 | |
| 62 | // Eof States |
| 63 | typedef enum |
| 64 | { |
| 65 | kEofStateNone, |
| 66 | kEofStateDelayed, |
| 67 | kEofStateImmediate |
| 68 | } EofState; |
| 69 | |
62 | 70 | class StreamInfo |
63 | 71 | { |
64 | 72 | public: |
… |
… |
class DecoderBase |
115 | 123 | char testbuf[kDecoderProbeBufferSize], |
116 | 124 | int testbufsize = kDecoderProbeBufferSize) = 0; |
117 | 125 | |
118 | | virtual void SetEof(bool eof) { ateof = eof; } |
119 | | bool GetEof(void) const { return ateof; } |
| 126 | virtual void SetEof(EofState eof) { ateof = eof; } |
| 127 | virtual void SetEof(bool eof) { ateof = eof?kEofStateDelayed:kEofStateNone; } |
| 128 | EofState GetEof(void) { return ateof; } |
120 | 129 | |
121 | 130 | void SetSeekSnap(uint64_t snap) { seeksnap = snap; } |
122 | 131 | uint64_t GetSeekSnap(void) const { return seeksnap; } |
… |
… |
class DecoderBase |
263 | 272 | int keyframedist; |
264 | 273 | long long indexOffset; |
265 | 274 | |
266 | | bool ateof; |
| 275 | EofState ateof; |
267 | 276 | bool exitafterdecoded; |
268 | 277 | bool transcoding; |
269 | 278 | |
diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
index 9f972fe..6b85715 100644
a
|
b
|
bool MythPlayer::PrebufferEnoughFrames(int min_buffers) |
2077 | 2077 | return false; |
2078 | 2078 | |
2079 | 2079 | if (!(min_buffers ? (videoOutput->ValidVideoFrames() >= min_buffers) : |
| 2080 | (GetEof() != kEofStateNone) || |
2080 | 2081 | (videoOutput->hasHWAcceleration() ? |
2081 | 2082 | videoOutput->EnoughPrebufferedFrames() : |
2082 | 2083 | videoOutput->EnoughDecodedFrames()))) |
… |
… |
void MythPlayer::SwitchToProgram(void) |
2479 | 2480 | { |
2480 | 2481 | OpenDummy(); |
2481 | 2482 | ResetPlaying(); |
2482 | | SetEof(false); |
| 2483 | SetEof(kEofStateNone); |
2483 | 2484 | delete pginfo; |
2484 | 2485 | return; |
2485 | 2486 | } |
… |
… |
void MythPlayer::SwitchToProgram(void) |
2501 | 2502 | QString("(card type: %1).") |
2502 | 2503 | .arg(player_ctx->tvchain->GetCardType(newid))); |
2503 | 2504 | LOG(VB_GENERAL, LOG_ERR, player_ctx->tvchain->toString()); |
2504 | | SetEof(true); |
| 2505 | SetEof(kEofStateImmediate); |
2505 | 2506 | SetErrored(tr("Error opening switch program buffer")); |
2506 | 2507 | delete pginfo; |
2507 | 2508 | return; |
2508 | 2509 | } |
2509 | 2510 | |
2510 | | if (GetEof()) |
| 2511 | if (GetEof() != kEofStateNone) |
2511 | 2512 | { |
2512 | 2513 | discontinuity = true; |
2513 | 2514 | ResetCaptions(); |
… |
… |
void MythPlayer::SwitchToProgram(void) |
2546 | 2547 | if (IsErrored()) |
2547 | 2548 | { |
2548 | 2549 | LOG(VB_GENERAL, LOG_ERR, LOC + "SwitchToProgram failed."); |
2549 | | SetEof(true); |
| 2550 | SetEof(kEofStateDelayed); |
2550 | 2551 | return; |
2551 | 2552 | } |
2552 | 2553 | |
2553 | | SetEof(false); |
| 2554 | SetEof(kEofStateNone); |
2554 | 2555 | |
2555 | 2556 | // the bitrate is reset by player_ctx->buffer->OpenFile()... |
2556 | 2557 | if (decoder) |
… |
… |
void MythPlayer::FileChangedCallback(void) |
2577 | 2578 | player_ctx->buffer->Reset(false, true); |
2578 | 2579 | else |
2579 | 2580 | player_ctx->buffer->Reset(false, true, true); |
2580 | | SetEof(false); |
| 2581 | SetEof(kEofStateNone); |
2581 | 2582 | Play(); |
2582 | 2583 | |
2583 | 2584 | player_ctx->SetPlayerChangingBuffers(false); |
… |
… |
void MythPlayer::JumpToProgram(void) |
2618 | 2619 | { |
2619 | 2620 | OpenDummy(); |
2620 | 2621 | ResetPlaying(); |
2621 | | SetEof(false); |
| 2622 | SetEof(kEofStateNone); |
2622 | 2623 | delete pginfo; |
2623 | 2624 | inJumpToProgramPause = false; |
2624 | 2625 | return; |
… |
… |
void MythPlayer::JumpToProgram(void) |
2643 | 2644 | QString("(card type: %1).") |
2644 | 2645 | .arg(player_ctx->tvchain->GetCardType(newid))); |
2645 | 2646 | LOG(VB_GENERAL, LOG_ERR, player_ctx->tvchain->toString()); |
2646 | | SetEof(true); |
| 2647 | SetEof(kEofStateImmediate); |
2647 | 2648 | SetErrored(tr("Error opening jump program file buffer")); |
2648 | 2649 | delete pginfo; |
2649 | 2650 | inJumpToProgramPause = false; |
… |
… |
void MythPlayer::JumpToProgram(void) |
2669 | 2670 | return; |
2670 | 2671 | } |
2671 | 2672 | |
2672 | | SetEof(false); |
| 2673 | SetEof(kEofStateNone); |
2673 | 2674 | |
2674 | 2675 | // the bitrate is reset by player_ctx->buffer->OpenFile()... |
2675 | 2676 | player_ctx->buffer->UpdateRawBitrate(decoder->GetRawBitrate()); |
… |
… |
void MythPlayer::EventLoop(void) |
2820 | 2821 | player_ctx->tvchain->JumpToNext(true, 1); |
2821 | 2822 | JumpToProgram(); |
2822 | 2823 | } |
2823 | | else if ((!allpaused || GetEof()) && player_ctx->tvchain && |
| 2824 | else if ((!allpaused || (GetEof() != kEofStateNone)) && player_ctx->tvchain && |
2824 | 2825 | (decoder && !decoder->GetWaitForChange())) |
2825 | 2826 | { |
2826 | 2827 | // Switch to the next program in livetv |
… |
… |
void MythPlayer::EventLoop(void) |
2880 | 2881 | } |
2881 | 2882 | |
2882 | 2883 | // Handle end of file |
2883 | | if (GetEof() && !allpaused) |
| 2884 | EofState _eof = GetEof(); |
| 2885 | if ((_eof != kEofStateNone) && !allpaused) |
2884 | 2886 | { |
2885 | 2887 | #ifdef USING_MHEG |
2886 | 2888 | if (interactiveTV && interactiveTV->StreamStarted(false)) |
… |
… |
void MythPlayer::EventLoop(void) |
2896 | 2898 | return; |
2897 | 2899 | } |
2898 | 2900 | |
2899 | | SetPlaying(false); |
2900 | | return; |
| 2901 | if (_eof == kEofStateImmediate) |
| 2902 | { |
| 2903 | SetPlaying(false); |
| 2904 | return; |
| 2905 | } |
| 2906 | LOG(VB_PLAYBACK, LOG_INFO, QString("waiting for no video frames %1").arg(videoOutput->ValidVideoFrames())); |
| 2907 | if (videoOutput && videoOutput->ValidVideoFrames() < 3) |
| 2908 | { |
| 2909 | SetPlaying(false); |
| 2910 | return; |
| 2911 | } |
2901 | 2912 | } |
2902 | 2913 | |
2903 | 2914 | // Handle rewind |
… |
… |
void MythPlayer::EventLoop(void) |
2915 | 2926 | if (fftime > 0) |
2916 | 2927 | { |
2917 | 2928 | DoFastForward(fftime, kInaccuracyDefault); |
2918 | | if (GetEof()) |
| 2929 | if (GetEof() != kEofStateNone) |
2919 | 2930 | return; |
2920 | 2931 | } |
2921 | 2932 | } |
… |
… |
void MythPlayer::EventLoop(void) |
2977 | 2988 | if (!(endExitPrompt == 1 && !player_ctx->IsPIP() && |
2978 | 2989 | player_ctx->GetState() == kState_WatchingPreRecorded)) |
2979 | 2990 | { |
2980 | | SetEof(true); |
| 2991 | SetEof(kEofStateDelayed); |
2981 | 2992 | } |
2982 | 2993 | } |
2983 | 2994 | else |
… |
… |
void MythPlayer::DecoderPauseCheck(void) |
3084 | 3095 | } |
3085 | 3096 | |
3086 | 3097 | //// FIXME - move the eof ownership back into MythPlayer |
3087 | | bool MythPlayer::GetEof(void) |
| 3098 | EofState MythPlayer::GetEof(void) |
3088 | 3099 | { |
3089 | 3100 | if (is_current_thread(playerThread)) |
3090 | | return decoder ? decoder->GetEof() : true; |
| 3101 | return decoder ? decoder->GetEof() : kEofStateImmediate; |
3091 | 3102 | |
3092 | 3103 | if (!decoder_change_lock.tryLock(50)) |
3093 | | return false; |
3094 | | |
3095 | | bool eof = decoder ? decoder->GetEof() : true; |
| 3104 | return kEofStateNone; |
| 3105 | |
| 3106 | EofState eof = decoder ? decoder->GetEof() : kEofStateImmediate; |
3096 | 3107 | decoder_change_lock.unlock(); |
3097 | 3108 | return eof; |
3098 | 3109 | } |
3099 | 3110 | |
3100 | | void MythPlayer::SetEof(bool eof) |
| 3111 | void MythPlayer::SetEof(EofState eof) |
3101 | 3112 | { |
3102 | 3113 | if (is_current_thread(playerThread)) |
3103 | 3114 | { |
… |
… |
void MythPlayer::DecoderLoop(bool pause) |
3159 | 3170 | decoder_change_lock.unlock(); |
3160 | 3171 | } |
3161 | 3172 | |
3162 | | bool obey_eof = GetEof() && |
3163 | | !(GetEof() && player_ctx->tvchain && !allpaused); |
| 3173 | bool obey_eof = (GetEof() != kEofStateNone) && |
| 3174 | !((GetEof() != kEofStateNone) && player_ctx->tvchain && !allpaused); |
3164 | 3175 | if (isDummy || ((decoderPaused || ffrew_skip == 0 || obey_eof) && |
3165 | 3176 | !decodeOneFrame)) |
3166 | 3177 | { |
… |
… |
bool MythPlayer::TranscodeGetNextFrame( |
4475 | 4486 | if (!decoder->GetFrame(kDecodeAV)) |
4476 | 4487 | return false; |
4477 | 4488 | |
4478 | | if (GetEof()) |
| 4489 | if (GetEof() != kEofStateNone) |
4479 | 4490 | return false; |
4480 | 4491 | |
4481 | 4492 | if (honorCutList && !deleteMap.IsEmpty()) |
… |
… |
bool MythPlayer::TranscodeGetNextFrame( |
4501 | 4512 | did_ff = 1; |
4502 | 4513 | } |
4503 | 4514 | } |
4504 | | if (GetEof()) |
| 4515 | if (GetEof() != kEofStateNone) |
4505 | 4516 | return false; |
4506 | 4517 | is_key = decoder->IsLastFrameKey(); |
4507 | 4518 | |
… |
… |
bool MythPlayer::SetStream(const QString &stream) |
4926 | 4937 | player_ctx->buffer->GetType() == ICRingBuffer::kRingBufferType) |
4927 | 4938 | { |
4928 | 4939 | // Restore livetv |
4929 | | SetEof(true); |
| 4940 | SetEof(kEofStateDelayed); |
4930 | 4941 | player_ctx->tvchain->JumpToNext(false, 1); |
4931 | 4942 | player_ctx->tvchain->JumpToNext(true, 1); |
4932 | 4943 | } |
… |
… |
void MythPlayer::JumpToStream(const QString &stream) |
4956 | 4967 | if (!player_ctx->buffer->IsOpen()) |
4957 | 4968 | { |
4958 | 4969 | LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToStream buffer OpenFile failed"); |
4959 | | SetEof(true); |
| 4970 | SetEof(kEofStateImmediate); |
4960 | 4971 | SetErrored(QObject::tr("Error opening remote stream buffer")); |
4961 | 4972 | return; |
4962 | 4973 | } |
… |
… |
void MythPlayer::JumpToStream(const QString &stream) |
4969 | 4980 | if (OpenFile(120) < 0) // 120 retries ~= 60 seconds |
4970 | 4981 | { |
4971 | 4982 | LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToStream OpenFile failed."); |
4972 | | SetEof(true); |
| 4983 | SetEof(kEofStateImmediate); |
4973 | 4984 | SetErrored(QObject::tr("Error opening remote stream")); |
4974 | 4985 | return; |
4975 | 4986 | } |
… |
… |
void MythPlayer::JumpToStream(const QString &stream) |
4985 | 4996 | .arg(player_ctx->buffer->GetRealFileSize()).arg(decoder->GetRawBitrate()) |
4986 | 4997 | .arg(totalLength).arg(totalFrames).arg(decoder->GetFPS()) ); |
4987 | 4998 | |
4988 | | SetEof(false); |
| 4999 | SetEof(kEofStateNone); |
4989 | 5000 | |
4990 | 5001 | // the bitrate is reset by player_ctx->buffer->OpenFile()... |
4991 | 5002 | player_ctx->buffer->UpdateRawBitrate(decoder->GetRawBitrate()); |
diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
index 695ff18..2728b10 100644
a
|
b
|
class MTV_PUBLIC MythPlayer |
142 | 142 | void SetLength(int len) { totalLength = len; } |
143 | 143 | void SetFramesPlayed(uint64_t played); |
144 | 144 | void SetVideoFilters(const QString &override); |
145 | | void SetEof(bool eof); |
| 145 | void SetEof(EofState eof); |
146 | 146 | void SetPIPActive(bool is_active) { pip_active = is_active; } |
147 | 147 | void SetPIPVisible(bool is_visible) { pip_visible = is_visible; } |
148 | 148 | |
… |
… |
class MTV_PUBLIC MythPlayer |
198 | 198 | bool IsPaused(void) const { return allpaused; } |
199 | 199 | bool GetRawAudioState(void) const; |
200 | 200 | bool GetLimitKeyRepeat(void) const { return limitKeyRepeat; } |
201 | | bool GetEof(void); |
| 201 | EofState GetEof(void); |
202 | 202 | bool IsErrored(void) const; |
203 | 203 | bool IsPlaying(uint wait_ms = 0, bool wait_for = true) const; |
204 | 204 | bool AtNormalSpeed(void) const { return next_normal_speed; } |