OpenShot Library | libopenshot  0.1.2
FFmpegReader.h
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Header file for FFmpegReader class
4  * @author Jonathan Thomas <jonathan@openshot.org>, Fabrice Bellard
5  *
6  * @section LICENSE
7  *
8  * Copyright (c) 2008-2013 OpenShot Studios, LLC, Fabrice Bellard
9  * (http://www.openshotstudios.com). This file is part of
10  * OpenShot Library (http://www.openshot.org), an open-source project
11  * dedicated to delivering high quality video editing and animation solutions
12  * to the world.
13  *
14  * This file is originally based on the Libavformat API example, and then modified
15  * by the libopenshot project.
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_FFMPEG_READER_H
32 #define OPENSHOT_FFMPEG_READER_H
33 
34 #include "ReaderBase.h"
35 
36 // Include FFmpeg headers and macros
37 #include "FFmpegUtilities.h"
38 
39 #include <cmath>
40 #include <ctime>
41 #include <iostream>
42 #include <stdio.h>
43 #include <tr1/memory>
44 #include "Cache.h"
45 #include "Exceptions.h"
46 #include "OpenMPUtilities.h"
47 
48 
49 using namespace std;
50 
51 namespace openshot
52 {
53  /**
54  * @brief This struct holds the associated video frame and starting sample # for an audio packet.
55  *
56  * Because audio packets do not match up with video frames, this helps determine exactly
57  * where the audio packet's samples belong.
58  */
60  {
61  int frame;
63  int is_near(AudioLocation location, int samples_per_frame, int amount);
64  };
65 
66  /**
67  * @brief This class uses the FFmpeg libraries, to open video files and audio files, and return
68  * openshot::Frame objects for any frame in the file.
69  *
70  * All seeking and caching is handled internally, and the primary public interface is the GetFrame()
71  * method. To use this reader, simply create an instance of this class, and call the GetFrame method
72  * to start retrieving frames. Use the <b>info</b> struct to obtain information on the file, such as the length
73  * (# of frames), height, width, bit rate, frames per second (fps), etc...
74  *
75  * @code
76  * // Create a reader for a video
77  * FFmpegReader r("MyAwesomeVideo.webm");
78  * r.Open(); // Open the reader
79  *
80  * // Get frame number 1 from the video
81  * tr1::shared_ptr<Frame> f = r.GetFrame(1);
82  *
83  * // Now that we have an openshot::Frame object, lets have some fun!
84  * f->Display(); // Display the frame on the screen
85  * f->DisplayWaveform(); // Display the audio waveform as an image
86  * f->Play(); // Play the audio through your speaker
87  *
88  * // Close the reader
89  * r.Close();
90  * @endcode
91  */
92  class FFmpegReader : public ReaderBase
93  {
94  private:
95  string path;
96 
97  AVFormatContext *pFormatCtx;
98  int i, videoStream, audioStream;
99  AVCodecContext *pCodecCtx, *aCodecCtx;
100  AVStream *pStream, *aStream;
101  AVPacket *packet;
102  AVPicture *pFrame;
103  bool is_open;
104  bool is_duration_known;
105  bool check_interlace;
106  bool check_fps;
107  bool has_missing_frames;
108 
109  int num_of_rescalers;
110  int rescaler_position;
111  vector<SwsContext*> image_rescalers;
112 
113  Cache working_cache;
114  Cache missing_frames;
115  map<AVPacket*, AVPacket*> packets;
116  map<AVPicture*, AVPicture*> frames;
117  map<long int, long int> processing_video_frames;
118  multimap<long int, long int> processing_audio_frames;
119  map<long int, long int> processed_video_frames;
120  map<long int, long int> processed_audio_frames;
121  multimap<long int, long int> missing_video_frames;
122  multimap<long int, long int> missing_audio_frames;
123  multimap<long int, long int> duplicate_video_frames;
124  map<long int, int> checked_frames;
125  AudioLocation previous_packet_location;
126 
127  // DEBUG VARIABLES (FOR AUDIO ISSUES)
128  int prev_samples;
129  long int prev_pts;
130  long int pts_total;
131  long int pts_counter;
132  long int num_packets_since_video_frame;
133  long int num_checks_since_final;
134  tr1::shared_ptr<Frame> last_video_frame;
135 
136  bool is_seeking;
137  long int seeking_pts;
138  long int seeking_frame;
139  bool is_video_seek;
140  int seek_count;
141  long int seek_audio_frame_found;
142  long int seek_video_frame_found;
143 
144  long int audio_pts_offset;
145  long int video_pts_offset;
146  long int last_frame;
147  long int largest_frame_processed;
148  long int current_video_frame; // can't reliably use PTS of video to determine this
149 
150  /// Check for the correct frames per second value by scanning the 1st few seconds of video packets.
151  void CheckFPS();
152 
153  /// Check the current seek position and determine if we need to seek again
154  bool CheckSeek(bool is_video);
155 
156  /// Check if a frame is missing and attempt to replace it's frame image (and
157  bool CheckMissingFrame(long int requested_frame);
158 
159  /// Check the working queue, and move finished frames to the finished queue
160  void CheckWorkingFrames(bool end_of_stream, long int requested_frame);
161 
162  /// Convert image to RGB format
163  void convert_image(long int current_frame, AVPicture *copyFrame, int width, int height, PixelFormat pix_fmt);
164 
165  /// Convert Frame Number into Audio PTS
166  long int ConvertFrameToAudioPTS(long int frame_number);
167 
168  /// Convert Frame Number into Video PTS
169  long int ConvertFrameToVideoPTS(long int frame_number);
170 
171  /// Convert Video PTS into Frame Number
172  long int ConvertVideoPTStoFrame(long int pts);
173 
174  /// Create a new Frame (or return an existing one) and add it to the working queue.
175  tr1::shared_ptr<Frame> CreateFrame(long int requested_frame);
176 
177  /// Calculate Starting video frame and sample # for an audio PTS
178  AudioLocation GetAudioPTSLocation(long int pts);
179 
180  /// Get an AVFrame (if any)
181  bool GetAVFrame();
182 
183  /// Get the next packet (if any)
184  int GetNextPacket();
185 
186  /// Get the smallest video frame that is still being processed
187  long int GetSmallestVideoFrame();
188 
189  /// Get the smallest audio frame that is still being processed
190  long int GetSmallestAudioFrame();
191 
192  /// Get the PTS for the current video packet
193  long int GetVideoPTS();
194 
195  /// Init a collection of software rescalers (thread safe)
196  void InitScalers();
197 
198  /// Remove partial frames due to seek
199  bool IsPartialFrame(long int requested_frame);
200 
201  /// Process a video packet
202  void ProcessVideoPacket(long int requested_frame);
203 
204  /// Process an audio packet
205  void ProcessAudioPacket(long int requested_frame, long int target_frame, int starting_sample);
206 
207  /// Read the stream until we find the requested Frame
208  tr1::shared_ptr<Frame> ReadStream(long int requested_frame);
209 
210  /// Remove AVFrame from cache (and deallocate it's memory)
211  void RemoveAVFrame(AVPicture*);
212 
213  /// Remove AVPacket from cache (and deallocate it's memory)
214  void RemoveAVPacket(AVPacket*);
215 
216  /// Remove & deallocate all software scalers
217  void RemoveScalers();
218 
219  /// Seek to a specific Frame. This is not always frame accurate, it's more of an estimation on many codecs.
220  void Seek(long int requested_frame) throw(TooManySeeks);
221 
222  /// Update PTS Offset (if any)
223  void UpdatePTSOffset(bool is_video);
224 
225  /// Update File Info for audio streams
226  void UpdateAudioInfo();
227 
228  /// Update File Info for video streams
229  void UpdateVideoInfo();
230 
231  public:
232  /// Final cache object used to hold final frames
234 
235  /// Enable or disable seeking. Seeking can more quickly locate the requested frame, but some
236  /// codecs have trouble seeking, and can introduce artifacts or blank images into the video.
238 
239  /// Constructor for FFmpegReader. This automatically opens the media file and loads
240  /// frame 1, or it throws one of the following exceptions.
241  FFmpegReader(string path) throw(InvalidFile, NoStreamsFound, InvalidCodec);
242 
243  /// Destructor
244  ~FFmpegReader();
245 
246  /// Close File
247  void Close();
248 
249  /// Get the cache object used by this reader
250  Cache* GetCache() { return &final_cache; };
251 
252  /// Get a shared pointer to a openshot::Frame object for a specific frame number of this reader.
253  ///
254  /// @returns The requested frame of video
255  /// @param requested_frame The frame number that is requested.
256  tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(OutOfBoundsFrame, ReaderClosed, TooManySeeks);
257 
258  /// Determine if reader is open or closed
259  bool IsOpen() { return is_open; };
260 
261  /// Return the type name of the class
262  string Name() { return "FFmpegReader"; };
263 
264  /// Get and Set JSON methods
265  string Json(); ///< Generate JSON string of this object
266  void SetJson(string value) throw(InvalidJSON); ///< Load JSON string into this object
267  Json::Value JsonValue(); ///< Generate Json::JsonValue for this object
268  void SetJsonValue(Json::Value root) throw(InvalidFile); ///< Load Json::JsonValue into this object
269 
270  /// Open File - which is called by the constructor automatically
271  void Open() throw(InvalidFile, NoStreamsFound, InvalidCodec);
272  };
273 
274 }
275 
276 #endif
Header file for ReaderBase class.
Header file for OpenMPUtilities (set some common macros)
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:95
Exception when a reader is closed, and a frame is requested.
Definition: Exceptions.h:234
bool IsOpen()
Determine if reader is open or closed.
Definition: FFmpegReader.h:259
Header file for all Exception classes.
This class uses the FFmpeg libraries, to open video files and audio files, and return openshot::Frame...
Definition: FFmpegReader.h:92
Exception when no valid codec is found for a file.
Definition: Exceptions.h:122
Exception when no streams are found in the file.
Definition: Exceptions.h:192
Exception for files that can not be found or opened.
Definition: Exceptions.h:132
Header file for Cache class.
This class is a cache manager for Frame objects.
Definition: Cache.h:55
Cache * GetCache()
Get the cache object used by this reader.
Definition: FFmpegReader.h:250
Cache final_cache
Final cache object used to hold final frames.
Definition: FFmpegReader.h:233
#define PixelFormat
Exception for frames that are out of bounds.
Definition: Exceptions.h:202
This namespace is the default namespace for all code in the openshot library.
Exception for invalid JSON.
Definition: Exceptions.h:152
This struct holds the associated video frame and starting sample # for an audio packet.
Definition: FFmpegReader.h:59
string Name()
Return the type name of the class.
Definition: FFmpegReader.h:262
Header file for FFmpegUtilities.
Exception when too many seek attempts happen.
Definition: Exceptions.h:254