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