MythTV  master
cutter.cpp
Go to the documentation of this file.
1 
2 #include "cutter.h"
3 
4 #include <algorithm> // for min
5 using namespace std;
6 
7 #include <QMap> // for QMap
8 
9 #include "mythlogging.h"
10 
12 {
13  // Break each cut into two parts, the first for
14  // the player and the second for the transcode loop.
15  frm_dir_map_t remainingCutList;
16  int64_t start = 0;
17  int64_t leadinLength = 0;
18 
19  m_tracker.SetPlayerContext(ctx);
20  m_foreshortenedCutList.clear();
21 
22  for (auto it = deleteMap.begin(); it != deleteMap.end(); ++it)
23  {
24  switch(it.value())
25  {
26  case MARK_CUT_START:
27  m_foreshortenedCutList[it.key()] = MARK_CUT_START;
28  start = it.key();
29  break;
30 
31  case MARK_CUT_END:
32  leadinLength = min((int64_t)(it.key() - start),
33  (int64_t)MAXLEADIN);
34  if (leadinLength >= MINCUT)
35  {
36  m_foreshortenedCutList[it.key() - leadinLength + 2] =
38  remainingCutList[it.key() - leadinLength + 1] =
40  remainingCutList[it.key()] = MARK_CUT_END;
41  }
42  else
43  {
44  // Cut too short to use new method.
45  m_foreshortenedCutList[it.key()] = MARK_CUT_END;
46  }
47  break;
48 
49  default:
50  // Ignore all other mark types.
51  break;
52  }
53  }
54 
55  m_tracker.SetMap(remainingCutList);
56 }
57 
59 {
60  return m_foreshortenedCutList;
61 }
62 
63 void Cutter::Activate(float v2a, int64_t total)
64 {
65  m_active = true;
66  m_audioFramesPerVideoFrame = v2a;
67  m_totalFrames = total;
68  m_videoFramesToCut = 0;
69  m_audioFramesToCut = 0;
70  m_tracker.TrackerReset(0);
71 }
72 
73 void Cutter::NewFrame(int64_t currentFrame)
74 {
75  if (m_active)
76  {
77  if (m_videoFramesToCut == 0)
78  {
79  uint64_t jumpTo = 0;
80 
81  if (m_tracker.TrackerWantsToJump(currentFrame, jumpTo))
82  {
83  // Reset the tracker and work out how much video and audio
84  // to drop
85  m_tracker.TrackerReset(jumpTo);
86  m_videoFramesToCut = jumpTo - currentFrame;
87  m_audioFramesToCut += llroundf(m_videoFramesToCut *
88  m_audioFramesPerVideoFrame);
89  LOG(VB_GENERAL, LOG_INFO,
90  QString("Clean cut: discarding frame from %1 to %2: "
91  "vid %3 aud %4")
92  .arg(currentFrame).arg((long)jumpTo)
93  .arg(m_videoFramesToCut)
94  .arg(m_audioFramesToCut));
95  }
96  }
97  }
98 }
99 
101 {
102  if (m_videoFramesToCut == 0)
103  {
104  return false;
105  }
106 
107  // We are inside a cut. Inhibit use of this frame
108  m_videoFramesToCut--;
109 
110  if(m_videoFramesToCut == 0)
111  LOG(VB_GENERAL, LOG_INFO,
112  QString("Clean cut: end of video cut; audio frames left "
113  "to cut %1") .arg(m_audioFramesToCut));
114 
115  return true;
116 }
117 
118 bool Cutter::InhibitUseAudioFrames(int64_t frames, long *totalAudio)
119 {
120  int64_t delta = m_audioFramesToCut - frames;
121  if (delta < 0)
122  delta = -delta;
123 
124  if (m_audioFramesToCut == 0)
125  {
126  return false;
127  }
128  if (delta < m_audioFramesToCut)
129  {
130  // Drop the packet containing these frames if doing
131  // so gets us closer to zero left to drop
132  m_audioFramesToCut -= frames;
133  if(m_audioFramesToCut == 0)
134  LOG(VB_GENERAL, LOG_INFO,
135  QString("Clean cut: end of audio cut; vidio frames left "
136  "to cut %1") .arg(m_videoFramesToCut));
137  return true;
138  }
139 
140  // Don't drop this packet even though we still have frames to cut,
141  // because doing so would put us further out. Instead, inflate the
142  // callers record of how many audio frames have been output.
143  *totalAudio += m_audioFramesToCut;
144  m_audioFramesToCut = 0;
145  LOG(VB_GENERAL, LOG_INFO,
146  QString("Clean cut: end of audio cut; vidio frames left to "
147  "cut %1") .arg(m_videoFramesToCut));
148  return false;
149 }
150 
152 {
153  if (m_audioFramesToCut > 0)
154  {
155  // If the cutter is in the process of dropping audio then
156  // it is better to drop more audio rather than insert a dummy frame
157  m_audioFramesToCut += llroundf(m_audioFramesPerVideoFrame);
158  return true;
159  }
160  return false;
161 }
162 
164 {
165  if (m_audioFramesToCut > llroundf(m_audioFramesPerVideoFrame))
166  {
167  // If the cutter is in the process of dropping audio and the
168  // amount to drop is sufficient then we can drop less
169  // audio rather than drop a frame
170  m_audioFramesToCut -= llroundf(m_audioFramesPerVideoFrame);
171 
172  // But if it's a frame we are supposed to drop anyway, still do so,
173  // and record that we have
174  if (m_videoFramesToCut > 0)
175  {
176  m_videoFramesToCut-- ;
177  return false;
178  }
179  return true;
180  }
181  return false;
182 }
183 
184 /* vim: set expandtab tabstop=4 shiftwidth=4: */
185 
bool InhibitDropFrame(void)
Definition: cutter.cpp:163
void SetCutList(frm_dir_map_t &deleteMap, PlayerContext *ctx)
Definition: cutter.cpp:11
bool InhibitUseAudioFrames(int64_t frames, long *totalAudio)
Definition: cutter.cpp:118
void NewFrame(int64_t currentFrame)
Definition: cutter.cpp:73
bool InhibitUseVideoFrame(void)
Definition: cutter.cpp:100
bool InhibitDummyFrame(void)
Definition: cutter.cpp:151
void Activate(float v2a, int64_t total)
Definition: cutter.cpp:63
frm_dir_map_t AdjustedCutList() const
Definition: cutter.cpp:58
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
const char * frames[3]
Definition: element.c:46
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:81