OpenShot Library | libopenshot 0.3.1
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
34namespace 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
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
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
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
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:201
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:290
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:64
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.
CacheMemory * GetCache() override
Get the cache object used by this reader.
Definition: FrameMapper.h:258
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:25
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:55
This class represents a single frame of video (i.e. image & audio data)
Definition: Frame.h:91
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:480
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
Field(int64_t frame, bool isodd)
Definition: FrameMapper.h:62
This struct holds two fields which together make up a complete video frame.
Definition: FrameMapper.h:173
This struct holds a the range of samples needed by this frame.
Definition: FrameMapper.h:76
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
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
void Shift(int64_t samples, openshot::Fraction fps, int sample_rate, int channels, bool right_side)
Definition: FrameMapper.h:148