1 /** 2 * @file 3 * @brief Header file for the FrameMapper class 4 * @author Jonathan Thomas <jonathan@openshot.org> 5 * 6 * @ref License 7 */ 8 9 /* LICENSE 10 * 11 * Copyright (c) 2008-2019 OpenShot Studios, LLC 12 * <http://www.openshotstudios.com/>. This file is part of 13 * OpenShot Library (libopenshot), an open-source project dedicated to 14 * delivering high quality video editing and animation solutions to the 15 * world. For more information visit <http://www.openshot.org/>. 16 * 17 * OpenShot Library (libopenshot) is free software: you can redistribute it 18 * and/or modify it under the terms of the GNU Lesser General Public License 19 * as published by the Free Software Foundation, either version 3 of the 20 * License, or (at your option) any later version. 21 * 22 * OpenShot Library (libopenshot) is distributed in the hope that it will be 23 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU Lesser General Public License for more details. 26 * 27 * You should have received a copy of the GNU Lesser General Public License 28 * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>. 29 */ 30 31 #ifndef OPENSHOT_FRAMEMAPPER_H 32 #define OPENSHOT_FRAMEMAPPER_H 33 34 #include <assert.h> 35 #include <iostream> 36 #include <cmath> 37 #include <vector> 38 #include <memory> 39 #include "CacheMemory.h" 40 #include "ReaderBase.h" 41 #include "Frame.h" 42 #include "Fraction.h" 43 #include "KeyFrame.h" 44 45 46 // Include FFmpeg headers and macros 47 #include "FFmpegUtilities.h" 48 #include "OpenMPUtilities.h" 49 50 51 namespace openshot 52 { 53 /** 54 * @brief This enumeration determines how frame rates are increased or decreased. 55 * 56 * Pull-down techniques are only needed to remove artificial fields added when converting 57 * between 24 fps (film) and television fps (29.97 fps NTSC or 25 fps PAL). 58 */ 59 enum PulldownType 60 { 61 PULLDOWN_CLASSIC, ///< Classic 2:3:2:3 pull-down 62 PULLDOWN_ADVANCED, ///< Advanced 2:3:3:2 pull-down (minimal dirty frames) 63 PULLDOWN_NONE, ///< Do not apply pull-down techniques, just repeat or skip entire frames 64 }; 65 66 /** 67 * @brief This struct holds a single field (half a frame). 68 * 69 * A frame of video is made up of 2 fields (half a frame). This struct points to which original 70 * frame, and whether this is the ODD or EVEN lines (i.e. top or bottom). 71 */ 72 struct Field 73 { 74 int64_t Frame; 75 bool isOdd; 76 FieldField77 Field() : Frame(0), isOdd(true) { }; 78 FieldField79 Field(int64_t frame, bool isodd) 80 { 81 Frame = frame; 82 isOdd = isodd; 83 } 84 }; 85 86 /** 87 * @brief This struct holds a the range of samples needed by this frame 88 * 89 * When frame rate is changed, the audio needs to be redistributed among the remaining 90 * frames. This struct holds the range samples needed by the this frame. 91 */ 92 struct SampleRange 93 { 94 int64_t frame_start; 95 int sample_start; 96 97 int64_t frame_end; 98 int sample_end; 99 100 int total; 101 }; 102 103 /** 104 * @brief This struct holds two fields which together make up a complete video frame. 105 * 106 * These fields can point at different original frame numbers, for example the odd lines from 107 * frame 3, and the even lines of frame 4, if required by a pull-down technique. 108 */ 109 struct MappedFrame 110 { 111 Field Odd; 112 Field Even; 113 SampleRange Samples; 114 }; 115 116 117 /** 118 * @brief This class creates a mapping between 2 different frame rates, applying a specific pull-down technique. 119 * 120 * This class creates a mapping between 2 different video files, and supports many pull-down techniques, 121 * such as 2:3:2:3 or 2:3:3:2, and also supports inverse telecine. Pull-down techniques are only needed to remove 122 * artificial fields added when converting between 24 fps (film) and television fps (29.97 fps NTSC or 25 fps PAL). 123 * 124 * The <b>following graphic</b> displays a how frame rates are mapped, and how time remapping affects the order 125 * of frames returned from the FrameMapper. 126 * \image html /doc/images/FrameMapper.png 127 * 128 * Please see the following <b>Example Code</b>: 129 * \code 130 * // Create a frame mapper for a reader, and convert the frame rate (from 24 fps to 29.97 fps) 131 * FrameMapper mapping(reader, Fraction(30000, 1001), PULLDOWN_CLASSIC, 44100, 2, LAYOUT_STEREO); 132 * std::shared_ptr<Frame> frame2 = mapping.GetFrame(2); 133 134 * // If you need to change the mapping... 135 * mapping.ChangeMapping(Fraction(24, 1), PULLDOWN_CLASSIC, 48000, 2, LAYOUT_MONO) 136 * \endcode 137 */ 138 class FrameMapper : public ReaderBase { 139 private: 140 bool field_toggle; // Internal odd / even toggle (used when building the mapping) 141 Fraction original; // The original frame rate 142 Fraction target; // The target frame rate 143 PulldownType pulldown; // The pull-down technique 144 ReaderBase *reader; // The source video reader 145 CacheMemory final_cache; // Cache of actual Frame objects 146 bool is_dirty; // When this is true, the next call to GetFrame will re-init the mapping 147 float parent_position; // Position of parent clip (which is used to generate the audio mapping) 148 float parent_start; // Start of parent clip (which is used to generate the audio mapping) 149 SWRCONTEXT *avr; // Audio resampling context object 150 151 // Internal methods used by init 152 void AddField(int64_t frame); 153 void AddField(Field field); 154 155 // Get Frame or Generate Blank Frame 156 std::shared_ptr<Frame> GetOrCreateFrame(int64_t number); 157 158 /// Adjust frame number for Clip position and start (which can result in a different number) 159 int64_t AdjustFrameNumber(int64_t clip_frame_number); 160 161 // Use the original and target frame rates and a pull-down technique to create 162 // a mapping between the original fields and frames or a video to a new frame rate. 163 // This might repeat or skip fields and frames of the original video, depending on 164 // whether the frame rate is increasing or decreasing. 165 void Init(); 166 167 public: 168 // Init some containers 169 std::vector<Field> fields; // List of all fields 170 std::vector<MappedFrame> frames; // List of all frames 171 172 /// Default constructor for openshot::FrameMapper class 173 FrameMapper(ReaderBase *reader, Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout); 174 175 /// Destructor 176 virtual ~FrameMapper(); 177 178 /// Change frame rate or audio mapping details 179 void ChangeMapping(Fraction target_fps, PulldownType pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout); 180 181 /// Close the openshot::FrameMapper and internal reader 182 void Close() override; 183 184 /// Get a frame based on the target frame rate and the new frame number of a frame 185 MappedFrame GetMappedFrame(int64_t TargetFrameNumber); 186 187 /// Get the cache object used by this reader GetCache()188 CacheMemory* GetCache() override { return &final_cache; }; 189 190 /// @brief This method is required for all derived classes of ReaderBase, and return the 191 /// openshot::Frame object, which contains the image and audio information for that 192 /// frame of video. 193 /// 194 /// @returns The requested frame of video 195 /// @param requested_frame The frame number that is requested. 196 std::shared_ptr<Frame> GetFrame(int64_t requested_frame) override; 197 198 /// Determine if reader is open or closed 199 bool IsOpen() override; 200 201 /// Return the type name of the class Name()202 std::string Name() override { return "FrameMapper"; }; 203 204 // Get and Set JSON methods 205 std::string Json() const override; ///< Generate JSON string of this object 206 void SetJson(const std::string value) override; ///< Load JSON string into this object 207 Json::Value JsonValue() const override; ///< Generate Json::Value for this object 208 void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object 209 210 /// Open the internal reader 211 void Open() override; 212 213 /// Print all of the original frames and which new frames they map to 214 void PrintMapping(); 215 216 /// Get the current reader 217 ReaderBase* Reader(); 218 219 /// Set the current reader Reader(ReaderBase * new_reader)220 void Reader(ReaderBase *new_reader) { reader = new_reader; } 221 222 /// Resample audio and map channels (if needed) 223 void ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t original_frame_number); 224 }; 225 } 226 227 #endif 228