OpenShot Library | libopenshot  0.5.0
FrameMapper.h
Go to the documentation of this file.
1 
9 // Copyright (c) 2008-2019 OpenShot Studios, LLC
10 //
11 // SPDX-License-Identifier: LGPL-3.0-or-later
12 
13 #ifndef OPENSHOT_FRAMEMAPPER_H
14 #define OPENSHOT_FRAMEMAPPER_H
15 
16 #include <assert.h>
17 #include <iostream>
18 #include <vector>
19 #include <memory>
20 
21 #include "AudioResampler.h"
22 #include "CacheMemory.h"
23 #include "ReaderBase.h"
24 #include "Frame.h"
25 #include "Fraction.h"
26 #include "KeyFrame.h"
27 
28 
29 // Include FFmpeg headers and macros
30 #include "FFmpegUtilities.h"
31 #include "OpenMPUtilities.h"
32 
33 
34 namespace openshot
35 {
43  {
47  };
48 
55  struct Field
56  {
57  int64_t Frame;
58  bool isOdd;
59  };
60 
67  struct SampleRange
68  {
69  int64_t frame_start;
71 
72  int64_t frame_end;
74 
76  void Extend(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side) {
77  int remaining_samples = samples;
78  while (remaining_samples > 0) {
79  if (right_side) {
80  // Extend range to the right
81  int samples_per_frame = Frame::GetSamplesPerFrame(frame_end, fps, sample_rate, channels);
82  if (remaining_samples + sample_end < samples_per_frame) {
83  sample_end += remaining_samples;
84  remaining_samples = 0;
85  } else {
86  frame_end++;
87  remaining_samples -= (samples_per_frame - sample_end);
88  sample_end = 0;
89  }
90  } else {
91  // Extend range to the left
92  if (sample_start - remaining_samples >= 0) {
93  sample_start -= remaining_samples;
94  remaining_samples = 0;
95  } else {
96  frame_start--;
97  remaining_samples -= (sample_start + 1);
98  sample_start = Frame::GetSamplesPerFrame(frame_start, fps, sample_rate, channels) - 1;
99  }
100  }
101  }
102 
103  // Increase total
104  total += samples;
105  }
106 
108  void Shrink(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side) {
109  int remaining_samples = samples;
110  while (remaining_samples > 0) {
111  if (right_side) {
112  // Shrink range on the right
113  if (sample_end - remaining_samples >= 0) {
114  sample_end -= remaining_samples;
115  remaining_samples = 0;
116  } else {
117  frame_end--;
118  int samples_per_frame = Frame::GetSamplesPerFrame(frame_end, fps, sample_rate, channels);
119  remaining_samples -= (sample_end + 1);
120  sample_end = samples_per_frame - 1;
121  }
122  } else {
123  // Shrink range on the left
124  int samples_per_frame = Frame::GetSamplesPerFrame(frame_start, fps, sample_rate, channels);
125  if (sample_start + remaining_samples < samples_per_frame) {
126  sample_start += remaining_samples;
127  remaining_samples = 0;
128  } else {
129  frame_start++;
130  remaining_samples -= (samples_per_frame - sample_start);
131  sample_start = 0;
132  }
133  }
134  }
135 
136  // Reduce total
137  total -= samples;
138  }
139 
140  void Shift(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side) {
141  // Extend each side of the range (to SHIFT the range) by adding (or subtracting) from both sides
142  // For example: [ range ]
143  // For example: [ range ]
144  if (right_side) {
145  // SHIFT both sides to the right
146  Extend(samples, fps, sample_rate, channels, true);
147  Shrink(samples, fps, sample_rate, channels, false);
148  } else {
149  // SHIFT both sides to the left
150  Extend(samples, fps, sample_rate, channels, false);
151  Shrink(samples, fps, sample_rate, channels, true);
152  }
153  }
154 
155  int total;
156  };
157 
164  struct MappedFrame
165  {
169  };
170 
171 
193  class FrameMapper : public ReaderBase {
194  private:
195  bool field_toggle; // Internal odd / even toggle (used when building the mapping)
196  Fraction original; // The original frame rate
197  Fraction target; // The target frame rate
198  PulldownType pulldown; // The pull-down technique
199  ReaderBase *reader; // The source video reader
200  CacheMemory final_cache; // Cache of actual Frame objects
201  bool is_dirty; // When this is true, the next call to GetFrame will re-init the mapping
202  float parent_position; // Position of parent clip (which is used to generate the audio mapping)
203  float parent_start; // Start of parent clip (which is used to generate the audio mapping)
204  int64_t previous_frame; // Used during resampling, to determine when a large gap is detected
205  SWRCONTEXT *avr; // Audio resampling context object
206 
207  // Time curve / direction
208  std::recursive_mutex directionMutex;
209  bool have_hint = false;
210  bool hint_increasing = true;
211  bool last_is_increasing = true;
212  bool last_dir_initialized = false;
213 
214  // Audio resampler (if resampling audio)
215  openshot::AudioResampler *resampler;
216 
217  // Internal methods used by init
218  void AddField(int64_t frame);
219  void AddField(int64_t frame, bool isOdd);
220  void AddField(Field field);
221 
222  // Clear both the fields & frames lists
223  void Clear();
224 
225  // Get Frame or Generate Blank Frame
226  std::shared_ptr<Frame> GetOrCreateFrame(int64_t number);
227 
229  int64_t AdjustFrameNumber(int64_t clip_frame_number);
230 
231  // Use the original and target frame rates and a pull-down technique to create
232  // a mapping between the original fields and frames or a video to a new frame rate.
233  // This might repeat or skip fields and frames of the original video, depending on
234  // whether the frame rate is increasing or decreasing.
235  void Init();
236 
237  public:
238  // Init some containers
239  std::vector<Field> fields; // List of all fields
240  std::vector<MappedFrame> frames; // List of all frames
241 
243  FrameMapper(ReaderBase *reader, Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout);
244 
246  virtual ~FrameMapper();
247 
249  void ChangeMapping(Fraction target_fps, PulldownType pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout);
250 
252  void Close() override;
253 
255  MappedFrame GetMappedFrame(int64_t TargetFrameNumber);
256 
258  CacheMemory* GetCache() override { return &final_cache; };
259 
266  std::shared_ptr<Frame> GetFrame(int64_t requested_frame) override;
267 
269  bool IsOpen() override;
270 
272  std::string Name() override { return "FrameMapper"; };
273 
274  // Get and Set JSON methods
275  std::string Json() const override;
276  void SetJson(const std::string value) override;
277  Json::Value JsonValue() const override;
278  void SetJsonValue(const Json::Value root) override;
279 
281  void Open() override;
282 
284  void SetDirectionHint(const bool increasing);
285 
287  void PrintMapping(std::ostream* out=&std::cout);
288 
290  ReaderBase* Reader();
291 
293  void Reader(ReaderBase *new_reader) { reader = new_reader; }
294 
296  void ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t original_frame_number);
297  };
298 }
299 
300 #endif
Header file for AudioResampler class.
Header file for CacheMemory class.
Header file for FFmpegUtilities.
#define SWRCONTEXT
Header file for Fraction class.
Header file for Frame class.
Header file for the Keyframe class.
Header file for OpenMPUtilities (set some common macros)
Header file for ReaderBase class.
This class is used to resample audio data for many sequential frames.
This class is a memory-based cache manager for Frame objects.
Definition: CacheMemory.h:29
This class represents a fraction.
Definition: Fraction.h:30
This class creates a mapping between 2 different frame rates, applying a specific pull-down technique...
Definition: FrameMapper.h:193
CacheMemory * GetCache() override
Get the cache object used by this reader.
Definition: FrameMapper.h:258
std::shared_ptr< Frame > GetFrame(int64_t requested_frame) override
This method is required for all derived classes of ReaderBase, and return the openshot::Frame object,...
void ChangeMapping(Fraction target_fps, PulldownType pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout)
Change frame rate or audio mapping details.
void Reader(ReaderBase *new_reader)
Set the current reader.
Definition: FrameMapper.h:293
MappedFrame GetMappedFrame(int64_t TargetFrameNumber)
Get a frame based on the target frame rate and the new frame number of a frame.
std::string Name() override
Return the type name of the class.
Definition: FrameMapper.h:272
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
bool IsOpen() override
Determine if reader is open or closed.
std::vector< Field > fields
Definition: FrameMapper.h:239
ReaderBase * Reader()
Get the current reader.
Definition: FrameMapper.cpp:65
std::vector< MappedFrame > frames
Definition: FrameMapper.h:240
void ResampleMappedAudio(std::shared_ptr< Frame > frame, int64_t original_frame_number)
Resample audio and map channels (if needed)
void Open() override
Open the internal reader.
void Close() override
Close the openshot::FrameMapper and internal reader.
std::string Json() const override
Generate JSON string of this object.
FrameMapper(ReaderBase *reader, Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout)
Default constructor for openshot::FrameMapper class.
Definition: FrameMapper.cpp:26
void SetDirectionHint(const bool increasing)
Set time-curve informed direction hint (from Clip class) for the next call to GetFrame.
void PrintMapping(std::ostream *out=&std::cout)
Print all of the original frames and which new frames they map to.
void SetJson(const std::string value) override
Load JSON string into this object.
Json::Value JsonValue() const override
Generate Json::Value for this object.
virtual ~FrameMapper()
Destructor.
Definition: FrameMapper.cpp:56
int GetSamplesPerFrame(openshot::Fraction fps, int sample_rate, int channels)
Calculate the # of samples per video frame (for the current frame number)
Definition: Frame.cpp:484
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:76
This namespace is the default namespace for all code in the openshot library.
Definition: Compressor.h:29
PulldownType
This enumeration determines how frame rates are increased or decreased.
Definition: FrameMapper.h:43
@ PULLDOWN_CLASSIC
Classic 2:3:2:3 pull-down.
Definition: FrameMapper.h:44
@ PULLDOWN_ADVANCED
Advanced 2:3:3:2 pull-down (minimal dirty frames)
Definition: FrameMapper.h:45
@ PULLDOWN_NONE
Do not apply pull-down techniques, just repeat or skip entire frames.
Definition: FrameMapper.h:46
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround,...
This struct holds a single field (half a frame).
Definition: FrameMapper.h:56
This struct holds two fields which together make up a complete video frame.
Definition: FrameMapper.h:165
This struct holds a the range of samples needed by this frame.
Definition: FrameMapper.h:68
void Shrink(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side)
Shrink SampleRange on either side.
Definition: FrameMapper.h:108
void Extend(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side)
Extend SampleRange on either side.
Definition: FrameMapper.h:76
void Shift(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side)
Definition: FrameMapper.h:140