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