MythTV  master
avformatdecoderbd.cpp
Go to the documentation of this file.
1 #include "bdringbuffer.h"
2 #include "mythbdplayer.h"
3 #include "avformatdecoderbd.h"
4 
5 #include "iso639.h"
6 
7 #define LOC QString("AFD_BD: ")
8 
10  MythPlayer *parent, const ProgramInfo &pginfo, PlayerFlags flags)
11  : AvFormatDecoder(parent, pginfo, flags)
12 {
13 }
14 
16 {
17  if (m_ringBuffer && m_ringBuffer->IsBD())
18  return m_ringBuffer->BD()->IsValidStream(streamid);
19  return AvFormatDecoder::IsValidStream(streamid);
20 }
21 
22 void AvFormatDecoderBD::Reset(bool reset_video_data, bool seek_reset, bool reset_file)
23 {
24  AvFormatDecoder::Reset(reset_video_data, seek_reset, reset_file);
26 }
27 
29 {
30  if (!m_ringBuffer->IsBD())
31  return;
32 
33  auto currentpos = (long long)(m_ringBuffer->BD()->GetCurrentTime() * m_fps);
34  m_framesPlayed = m_framesRead = currentpos ;
35  m_parent->SetFramesPlayed(currentpos + 1);
36 }
37 
38 bool AvFormatDecoderBD::DoRewindSeek(long long desiredFrame)
39 {
40  if (!m_ringBuffer->IsBD())
41  return false;
42 
43  m_ringBuffer->Seek(BDFindPosition(desiredFrame), SEEK_SET);
44  m_framesPlayed = m_framesRead = m_lastKey = desiredFrame + 1;
45  m_frameCounter += 100;
46  return true;
47 }
48 
49 void AvFormatDecoderBD::DoFastForwardSeek(long long desiredFrame, bool &needflush)
50 {
51  if (!m_ringBuffer->IsBD())
52  return;
53 
54  m_ringBuffer->Seek(BDFindPosition(desiredFrame), SEEK_SET);
55  needflush = true;
56  m_framesPlayed = m_framesRead = m_lastKey = desiredFrame + 1;
57  m_frameCounter += 100;
58 }
59 
61 {
62  if (!m_ringBuffer->IsBD())
63  return;
64 
65  if (m_streamsChanged)
66  {
67  // This was originally in HandleBDStreamChange
68  LOG(VB_PLAYBACK, LOG_INFO, LOC + "resetting");
69  QMutexLocker locker(avcodeclock);
70  Reset(true, false, false);
71  CloseCodecs();
73  ScanStreams(false);
74  avcodeclock->unlock();
75  m_streamsChanged=false;
76  }
77 
79  {
80  ResetPosMap();
83  }
84 }
85 
87  uint stream_index)
88 {
89  (void)subtitle_index;
90  if (m_ringBuffer && m_ringBuffer->IsBD() &&
91  stream_index < m_ic->nb_streams &&
92  m_ic->streams[stream_index] != nullptr)
93  {
94  return m_ringBuffer->BD()->GetSubtitleLanguage(m_ic->streams[stream_index]->id);
95  }
96 
97  return iso639_str3_to_key("und");
98 }
99 
100 int AvFormatDecoderBD::GetAudioLanguage(uint audio_index, uint stream_index)
101 {
102  (void)audio_index;
103  if (m_ringBuffer && m_ringBuffer->IsBD() &&
104  stream_index < m_ic->nb_streams &&
105  m_ic->streams[stream_index] != nullptr)
106  {
107  return m_ringBuffer->BD()->GetAudioLanguage(m_ic->streams[stream_index]->id);
108  }
109 
110  return iso639_str3_to_key("und");
111 }
112 
113 int AvFormatDecoderBD::ReadPacket(AVFormatContext *ctx, AVPacket* pkt, bool& /*storePacket*/)
114 {
115  QMutexLocker locker(avcodeclock);
116 
117  int result = av_read_frame(ctx, pkt);
118 
119  /* If we seem to have hit the end of the file, the ringbuffer may
120  * just be blocked in order to drain the ffmpeg buffers, so try
121  * unblocking it and reading again.
122  * If ffmpeg's buffers are empty, it takes a couple of goes to
123  * fill and read from them.
124  */
125  for (int count = 0; (count < 3) && (result == AVERROR_EOF); count++)
126  {
127  if (m_ringBuffer->BD()->IsReadingBlocked())
129 
130  result = av_read_frame(ctx, pkt);
131  }
132 
133  if (result >= 0)
134  {
135  pkt->dts = m_ringBuffer->BD()->AdjustTimestamp(pkt->dts);
136  pkt->pts = m_ringBuffer->BD()->AdjustTimestamp(pkt->pts);
137  }
138 
139  return result;
140 }
141 
142 long long AvFormatDecoderBD::BDFindPosition(long long desiredFrame)
143 {
144  if (!m_ringBuffer->IsBD())
145  return 0;
146 
147  int ffrewSkip = 1;
148  int current_speed = 0;
149  if (m_parent)
150  {
151  ffrewSkip = m_parent->GetFFRewSkip();
152  current_speed = (int)m_parent->GetNextPlaySpeed();
153  }
154 
155  if (ffrewSkip == 1 || ffrewSkip == 0)
156  {
157 #if 0
158  int diffTime = (int)ceil((desiredFrame - m_framesPlayed) / m_fps);
159  long long desiredTimePos = m_ringBuffer->BD()->GetCurrentTime() +
160  diffTime;
161  if (diffTime <= 0)
162  desiredTimePos--;
163  else
164  desiredTimePos++;
165 
166  if (desiredTimePos < 0)
167  desiredTimePos = 0;
168 #endif
169  return (desiredFrame * 90000LL / m_fps);
170  }
171  return current_speed;
172 }
ISO 639-1 and ISO 639-2 support functions.
PlayerFlags
Definition: mythplayer.h:86
bool IsValidStream(int streamid) override
unsigned long long m_frameCounter
Definition: decoderbase.h:308
int GetAudioLanguage(uint audio_index, uint stream_index) override
void Reset(bool reset_video_data, bool seek_reset, bool reset_file) override
bool IsReadingBlocked(void)
Definition: bdringbuffer.h:122
static int iso639_str3_to_key(const unsigned char *iso639_2)
Definition: iso639.h:63
uint64_t GetCurrentTime(void)
Definition: bdringbuffer.h:107
int ReadPacket(AVFormatContext *ctx, AVPacket *pkt, bool &storePacket) override
#define LOC
void SetFramesPlayed(uint64_t played)
Definition: mythplayer.cpp:878
void UpdateFramesPlayed(void) override
bool DoRewindSeek(long long desiredFrame) override
Holds information on recordings and videos.
Definition: programinfo.h:67
int64_t AdjustTimestamp(int64_t timestamp)
AvFormatDecoderBD(MythPlayer *parent, const ProgramInfo &pginfo, PlayerFlags flags)
bool IsValidStream(int streamid)
long long BDFindPosition(long long desiredFrame)
AVFormatContext * m_ic
int GetAudioLanguage(uint streamID)
virtual void ResetPosMap(void)
A decoder for video files.
long long m_framesPlayed
Definition: decoderbase.h:306
void DoFastForwardSeek(long long desiredFrame, bool &needflush) override
Seeks to the keyframe just before the desiredFrame if exact seeks is enabled, or the frame just after...
unsigned int uint
Definition: compat.h:140
bool IsBD(void) const
int GetFFRewSkip(void) const
Definition: mythplayer.h:221
int GetSubtitleLanguage(uint streamID)
int FindStreamInfo(void)
virtual bool SyncPositionMap(void)
Updates the position map used for skipping frames.
int ScanStreams(bool novideo)
bool AtNormalSpeed(void) const
Definition: mythplayer.h:254
long long m_lastKey
Definition: decoderbase.h:310
int GetSubtitleLanguage(uint subtitle_index, uint stream_index) override
Returns DVD Subtitle language.
bool TitleChanged(void)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
RingBuffer * m_ringBuffer
Definition: decoderbase.h:296
void Reset(bool reset_video_data, bool seek_reset, bool reset_file) override
QMutex * avcodeclock
This global variable is used to makes certain calls to avlib threadsafe.
void StreamChangeCheck(void) override
float GetNextPlaySpeed(void) const
Definition: mythplayer.h:226
long long Seek(long long pos, int whence, bool has_lock=false)
Seeks to a particular position in the file.
Definition: ringbuffer.cpp:510
const BDRingBuffer * BD(void) const
void UnblockReading(void)
Definition: bdringbuffer.h:121
long long m_framesRead
Definition: decoderbase.h:307
virtual bool IsValidStream(int)
MythPlayer * m_parent
Definition: decoderbase.h:293