OpenShot Library | libopenshot  0.3.2
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  Field() : Frame(0), isOdd(true) { };
61 
62  Field(int64_t frame, bool isodd)
63  {
64  Frame = frame;
65  isOdd = isodd;
66  }
67  };
68 
75  struct SampleRange
76  {
77  int64_t frame_start;
79 
80  int64_t frame_end;
82 
84  void Extend(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side) {
85  int remaining_samples = samples;
86  while (remaining_samples > 0) {
87  if (right_side) {
88  // Extend range to the right
89  int samples_per_frame = Frame::GetSamplesPerFrame(frame_end, fps, sample_rate, channels);
90  if (remaining_samples + sample_end < samples_per_frame) {
91  sample_end += remaining_samples;
92  remaining_samples = 0;
93  } else {
94  frame_end++;
95  remaining_samples -= (samples_per_frame - sample_end);
96  sample_end = 0;
97  }
98  } else {
99  // Extend range to the left
100  if (sample_start - remaining_samples >= 0) {
101  sample_start -= remaining_samples;
102  remaining_samples = 0;
103  } else {
104  frame_start--;
105  remaining_samples -= (sample_start + 1);
106  sample_start = Frame::GetSamplesPerFrame(frame_start, fps, sample_rate, channels) - 1;
107  }
108  }
109  }
110 
111  // Increase total
112  total += samples;
113  }
114 
116  void Shrink(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side) {
117  int remaining_samples = samples;
118  while (remaining_samples > 0) {
119  if (right_side) {
120  // Shrink range on the right
121  if (sample_end - remaining_samples >= 0) {
122  sample_end -= remaining_samples;
123  remaining_samples = 0;
124  } else {
125  frame_end--;
126  int samples_per_frame = Frame::GetSamplesPerFrame(frame_end, fps, sample_rate, channels);
127  remaining_samples -= (sample_end + 1);
128  sample_end = samples_per_frame - 1;
129  }
130  } else {
131  // Shrink range on the left
132  int samples_per_frame = Frame::GetSamplesPerFrame(frame_start, fps, sample_rate, channels);
133  if (sample_start + remaining_samples < samples_per_frame) {
134  sample_start += remaining_samples;
135  remaining_samples = 0;
136  } else {
137  frame_start++;
138  remaining_samples -= (samples_per_frame - sample_start);
139  sample_start = 0;
140  }
141  }
142  }
143 
144  // Reduce total
145  total -= samples;
146  }
147 
148  void Shift(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side) {
149  // Extend each side of the range (to SHIFT the range) by adding (or subtracting) from both sides
150  // For example: [ range ]
151  // For example: [ range ]
152  if (right_side) {
153  // SHIFT both sides to the right
154  Extend(samples, fps, sample_rate, channels, true);
155  Shrink(samples, fps, sample_rate, channels, false);
156  } else {
157  // SHIFT both sides to the left
158  Extend(samples, fps, sample_rate, channels, false);
159  Shrink(samples, fps, sample_rate, channels, true);
160  }
161  }
162 
163  int total;
164  };
165 
172  struct MappedFrame
173  {
177  };
178 
179 
201  class FrameMapper : public ReaderBase {
202  private:
203  bool field_toggle; // Internal odd / even toggle (used when building the mapping)
204  Fraction original; // The original frame rate
205  Fraction target; // The target frame rate
206  PulldownType pulldown; // The pull-down technique
207  ReaderBase *reader; // The source video reader
208  CacheMemory final_cache; // Cache of actual Frame objects
209  bool is_dirty; // When this is true, the next call to GetFrame will re-init the mapping
210  float parent_position; // Position of parent clip (which is used to generate the audio mapping)
211  float parent_start; // Start of parent clip (which is used to generate the audio mapping)
212  int64_t previous_frame; // Used during resampling, to determine when a large gap is detected
213  SWRCONTEXT *avr; // Audio resampling context object
214 
215  // Audio resampler (if resampling audio)
216  openshot::AudioResampler *resampler;
217 
218  // Internal methods used by init
219  void AddField(int64_t frame);
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 PrintMapping(std::ostream* out=&std::cout);
285 
287  ReaderBase* Reader();
288 
290  void Reader(ReaderBase *new_reader) { reader = new_reader; }
291 
293  void ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t original_frame_number);
294  };
295 }
296 
297 #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:779
openshot::FrameMapper::fields
std::vector< Field > fields
Definition: FrameMapper.h:239
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:824
Fraction.h
Header file for Fraction class.
openshot::Field::isOdd
bool isOdd
Definition: FrameMapper.h:58
openshot::Field::Field
Field(int64_t frame, bool isodd)
Definition: FrameMapper.h:62
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:643
openshot::Field::Field
Field()
Definition: FrameMapper.h:60
openshot::SampleRange::frame_end
int64_t frame_end
Definition: FrameMapper.h:80
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:116
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:290
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:272
openshot::Frame
This class represents a single frame of video (i.e. image & audio data)
Definition: Frame.h:90
openshot::FrameMapper::Json
std::string Json() const override
Generate JSON string of this object.
Definition: FrameMapper.cpp:721
KeyFrame.h
Header file for the Keyframe class.
openshot::SampleRange::sample_start
int sample_start
Definition: FrameMapper.h:78
openshot::MappedFrame::Even
Field Even
Definition: FrameMapper.h:175
openshot::FrameMapper::SetJsonValue
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
Definition: FrameMapper.cpp:765
openshot::FrameMapper::GetCache
CacheMemory * GetCache() override
Get the cache object used by this reader.
Definition: FrameMapper.h:258
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:677
openshot::SampleRange::frame_start
int64_t frame_start
Definition: FrameMapper.h:77
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:423
openshot::FrameMapper::frames
std::vector< MappedFrame > frames
Definition: FrameMapper.h:240
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:689
openshot::MappedFrame::Odd
Field Odd
Definition: FrameMapper.h:174
openshot::FrameMapper::IsOpen
bool IsOpen() override
Determine if reader is open or closed.
Definition: FrameMapper.cpp:669
CacheMemory.h
Header file for CacheMemory class.
openshot::MappedFrame::Samples
SampleRange Samples
Definition: FrameMapper.h:176
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:172
SWRCONTEXT
#define SWRCONTEXT
Definition: FFmpegUtilities.h:148
openshot::SampleRange
This struct holds a the range of samples needed by this frame.
Definition: FrameMapper.h:75
Frame.h
Header file for Frame class.
openshot::SampleRange::total
int total
Definition: FrameMapper.h:163
openshot::FrameMapper
This class creates a mapping between 2 different frame rates, applying a specific pull-down technique...
Definition: FrameMapper.h:201
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:728
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:339
openshot::SampleRange::Shift
void Shift(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side)
Definition: FrameMapper.h:148
openshot::SampleRange::sample_end
int sample_end
Definition: FrameMapper.h:81
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:742
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:84
openshot::PULLDOWN_CLASSIC
@ PULLDOWN_CLASSIC
Classic 2:3:2:3 pull-down.
Definition: FrameMapper.h:44