OpenShot Library | libopenshot  0.4.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  // Audio resampler (if resampling audio)
208  openshot::AudioResampler *resampler;
209 
210  // Internal methods used by init
211  void AddField(int64_t frame);
212  void AddField(int64_t frame, bool isOdd);
213  void AddField(Field field);
214 
215  // Clear both the fields & frames lists
216  void Clear();
217 
218  // Get Frame or Generate Blank Frame
219  std::shared_ptr<Frame> GetOrCreateFrame(int64_t number);
220 
222  int64_t AdjustFrameNumber(int64_t clip_frame_number);
223 
224  // Use the original and target frame rates and a pull-down technique to create
225  // a mapping between the original fields and frames or a video to a new frame rate.
226  // This might repeat or skip fields and frames of the original video, depending on
227  // whether the frame rate is increasing or decreasing.
228  void Init();
229 
230  public:
231  // Init some containers
232  std::vector<Field> fields; // List of all fields
233  std::vector<MappedFrame> frames; // List of all frames
234 
236  FrameMapper(ReaderBase *reader, Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout);
237 
239  virtual ~FrameMapper();
240 
242  void ChangeMapping(Fraction target_fps, PulldownType pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout);
243 
245  void Close() override;
246 
248  MappedFrame GetMappedFrame(int64_t TargetFrameNumber);
249 
251  CacheMemory* GetCache() override { return &final_cache; };
252 
259  std::shared_ptr<Frame> GetFrame(int64_t requested_frame) override;
260 
262  bool IsOpen() override;
263 
265  std::string Name() override { return "FrameMapper"; };
266 
267  // Get and Set JSON methods
268  std::string Json() const override;
269  void SetJson(const std::string value) override;
270  Json::Value JsonValue() const override;
271  void SetJsonValue(const Json::Value root) override;
272 
274  void Open() override;
275 
277  void PrintMapping(std::ostream* out=&std::cout);
278 
280  ReaderBase* Reader();
281 
283  void Reader(ReaderBase *new_reader) { reader = new_reader; }
284 
286  void ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t original_frame_number);
287  };
288 }
289 
290 #endif
openshot::FrameMapper::ChangeMapping
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.
Definition: FrameMapper.cpp:787
openshot::FrameMapper::fields
std::vector< Field > fields
Definition: FrameMapper.h:232
FFmpegUtilities.h
Header file for FFmpegUtilities.
openshot::FrameMapper::ResampleMappedAudio
void ResampleMappedAudio(std::shared_ptr< Frame > frame, int64_t original_frame_number)
Resample audio and map channels (if needed)
Definition: FrameMapper.cpp:832
Fraction.h
Header file for Fraction class.
openshot::Field::isOdd
bool isOdd
Definition: FrameMapper.h:58
openshot::FrameMapper::PrintMapping
void PrintMapping(std::ostream *out=&std::cout)
Print all of the original frames and which new frames they map to.
Definition: FrameMapper.cpp:651
openshot::SampleRange::frame_end
int64_t frame_end
Definition: FrameMapper.h:72
openshot
This namespace is the default namespace for all code in the openshot library.
Definition: Compressor.h:28
openshot::SampleRange::Shrink
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
openshot::Fraction
This class represents a fraction.
Definition: Fraction.h:30
openshot::FrameMapper::Reader
void Reader(ReaderBase *new_reader)
Set the current reader.
Definition: FrameMapper.h:283
openshot::Field
This struct holds a single field (half a frame).
Definition: FrameMapper.h:55
AudioResampler.h
Header file for AudioResampler class.
openshot::FrameMapper::Name
std::string Name() override
Return the type name of the class.
Definition: FrameMapper.h:265
openshot::FrameMapper::Json
std::string Json() const override
Generate JSON string of this object.
Definition: FrameMapper.cpp:729
KeyFrame.h
Header file for the Keyframe class.
openshot::SampleRange::sample_start
int sample_start
Definition: FrameMapper.h:70
openshot::MappedFrame::Even
Field Even
Definition: FrameMapper.h:167
openshot::FrameMapper::SetJsonValue
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
Definition: FrameMapper.cpp:773
openshot::FrameMapper::GetCache
CacheMemory * GetCache() override
Get the cache object used by this reader.
Definition: FrameMapper.h:251
openshot::AudioResampler
This class is used to resample audio data for many sequential frames.
Definition: AudioResampler.h:30
openshot::FrameMapper::Open
void Open() override
Open the internal reader.
Definition: FrameMapper.cpp:685
openshot::SampleRange::frame_start
int64_t frame_start
Definition: FrameMapper.h:69
openshot::FrameMapper::~FrameMapper
virtual ~FrameMapper()
Destructor.
Definition: FrameMapper.cpp:55
openshot::FrameMapper::GetFrame
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,...
Definition: FrameMapper.cpp:431
openshot::FrameMapper::frames
std::vector< MappedFrame > frames
Definition: FrameMapper.h:233
openshot::CacheMemory
This class is a memory-based cache manager for Frame objects.
Definition: CacheMemory.h:29
openshot::FrameMapper::Close
void Close() override
Close the openshot::FrameMapper and internal reader.
Definition: FrameMapper.cpp:697
openshot::MappedFrame::Odd
Field Odd
Definition: FrameMapper.h:166
openshot::FrameMapper::IsOpen
bool IsOpen() override
Determine if reader is open or closed.
Definition: FrameMapper.cpp:677
CacheMemory.h
Header file for CacheMemory class.
openshot::MappedFrame::Samples
SampleRange Samples
Definition: FrameMapper.h:168
openshot::FrameMapper::FrameMapper
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:25
openshot::MappedFrame
This struct holds two fields which together make up a complete video frame.
Definition: FrameMapper.h:164
SWRCONTEXT
#define SWRCONTEXT
Definition: FFmpegUtilities.h:150
openshot::SampleRange
This struct holds a the range of samples needed by this frame.
Definition: FrameMapper.h:67
Frame.h
Header file for Frame class.
openshot::SampleRange::total
int total
Definition: FrameMapper.h:155
openshot::FrameMapper
This class creates a mapping between 2 different frame rates, applying a specific pull-down technique...
Definition: FrameMapper.h:193
openshot::Frame::GetSamplesPerFrame
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
openshot::FrameMapper::JsonValue
Json::Value JsonValue() const override
Generate Json::Value for this object.
Definition: FrameMapper.cpp:736
openshot::PULLDOWN_ADVANCED
@ PULLDOWN_ADVANCED
Advanced 2:3:3:2 pull-down (minimal dirty frames)
Definition: FrameMapper.h:45
ReaderBase.h
Header file for ReaderBase class.
openshot::FrameMapper::GetMappedFrame
MappedFrame GetMappedFrame(int64_t TargetFrameNumber)
Get a frame based on the target frame rate and the new frame number of a frame.
Definition: FrameMapper.cpp:347
openshot::SampleRange::Shift
void Shift(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side)
Definition: FrameMapper.h:140
openshot::SampleRange::sample_end
int sample_end
Definition: FrameMapper.h:73
OpenMPUtilities.h
Header file for OpenMPUtilities (set some common macros)
openshot::ReaderBase
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:75
openshot::PulldownType
PulldownType
This enumeration determines how frame rates are increased or decreased.
Definition: FrameMapper.h:42
openshot::ChannelLayout
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround,...
Definition: ChannelLayouts.h:28
openshot::FrameMapper::Reader
ReaderBase * Reader()
Get the current reader.
Definition: FrameMapper.cpp:64
openshot::Field::Frame
int64_t Frame
Definition: FrameMapper.h:57
openshot::PULLDOWN_NONE
@ PULLDOWN_NONE
Do not apply pull-down techniques, just repeat or skip entire frames.
Definition: FrameMapper.h:46
openshot::FrameMapper::SetJson
void SetJson(const std::string value) override
Load JSON string into this object.
Definition: FrameMapper.cpp:750
openshot::SampleRange::Extend
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
openshot::PULLDOWN_CLASSIC
@ PULLDOWN_CLASSIC
Classic 2:3:2:3 pull-down.
Definition: FrameMapper.h:44