Improved support for missing frames and invalid PTS (which result in gaps and duplicate frames). Also changed frame number to larger data type, and did some code clean-up and refactoring. Less crashes, and more video support!

This commit is contained in:
Jonathan Thomas
2015-08-24 01:05:48 -05:00
parent 45f31bbabf
commit bfa050409c
54 changed files with 566 additions and 321 deletions

View File

@@ -56,8 +56,8 @@ namespace openshot {
{
private:
int64 max_bytes; ///< This is the max number of bytes to cache (0 = no limit)
map<int, tr1::shared_ptr<Frame> > frames; ///< This map holds the frame number and Frame objects
deque<int> frame_numbers; ///< This queue holds a sequential list of cached Frame numbers
map<long int, tr1::shared_ptr<Frame> > frames; ///< This map holds the frame number and Frame objects
deque<long int> frame_numbers; ///< This queue holds a sequential list of cached Frame numbers
/// Clean up cached frames that exceed the max number of bytes
void CleanUp();
@@ -80,20 +80,20 @@ namespace openshot {
/// @brief Add a Frame to the cache
/// @param frame_number The frame number of the cached frame
/// @param frame The openshot::Frame object needing to be cached.
void Add(int frame_number, tr1::shared_ptr<Frame> frame);
void Add(long int frame_number, tr1::shared_ptr<Frame> frame);
/// Clear the cache of all frames
void Clear();
/// Count the frames in the queue
int Count();
long int Count();
/// Display a list of cached frame numbers
void Display();
/// @brief Get a frame from the cache
/// @param frame_number The frame number of the cached frame
tr1::shared_ptr<Frame> GetFrame(int frame_number);
tr1::shared_ptr<Frame> GetFrame(long int frame_number);
/// Gets the maximum bytes value
int64 GetBytes();
@@ -106,11 +106,11 @@ namespace openshot {
/// @brief Move frame to front of queue (so it lasts longer)
/// @param frame_number The frame number of the cached frame
void MoveToFront(int frame_number);
void MoveToFront(long int frame_number);
/// @brief Remove a specific frame
/// @param frame_number The frame number of the cached frame
void Remove(int frame_number);
void Remove(long int frame_number);
/// @brief Set maximum bytes to a different amount
/// @param number_of_bytes The maximum bytes to allow in the cache. Once exceeded, the cache will purge the oldest frames.
@@ -122,7 +122,7 @@ namespace openshot {
/// @param height The height of the frame's image
/// @param sample_rate The sample rate of the frame's audio data
/// @param channels The number of audio channels in the frame
void SetMaxBytesFromInfo(int number_of_frames, int width, int height, int sample_rate, int channels);
void SetMaxBytesFromInfo(long int number_of_frames, int width, int height, int sample_rate, int channels);
};

View File

@@ -117,7 +117,7 @@ namespace openshot
bool does_folder_exist(string path);
/// Find the location of a frame in a chunk
ChunkLocation find_chunk_frame(int requested_frame);
ChunkLocation find_chunk_frame(long int requested_frame);
/// get a formatted path of a specific chunk
string get_chunk_path(int chunk_number, string folder, string extension);
@@ -150,7 +150,7 @@ namespace openshot
/// @brief Get an openshot::Frame object for a specific frame number of this reader.
/// @returns The requested frame (containing the image and audio)
/// @param requested_frame The frame number you want to retrieve
tr1::shared_ptr<Frame> GetFrame(int requested_frame) throw(ReaderClosed, ChunkNotFound);
tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(ReaderClosed, ChunkNotFound);
/// Determine if reader is open or closed
bool IsOpen() { return is_open; };

View File

@@ -121,7 +121,7 @@ namespace openshot {
bool manage_reader;
/// Adjust frame number minimum value
int adjust_frame_number_minimum(int frame_number);
int adjust_frame_number_minimum(long int frame_number);
/// Apply effects to the source frame (if any)
tr1::shared_ptr<Frame> apply_effects(tr1::shared_ptr<Frame> frame);
@@ -130,7 +130,7 @@ namespace openshot {
string get_file_extension(string path);
/// Adjust the audio and image of a time mapped frame
tr1::shared_ptr<Frame> get_time_mapped_frame(tr1::shared_ptr<Frame> frame, int frame_number) throw(ReaderClosed);
tr1::shared_ptr<Frame> get_time_mapped_frame(tr1::shared_ptr<Frame> frame, long int frame_number) throw(ReaderClosed);
/// Init default settings for a clip
void init_settings();
@@ -174,7 +174,7 @@ namespace openshot {
///
/// @returns The requested frame (containing the image)
/// @param requested_frame The frame number that is requested
tr1::shared_ptr<Frame> GetFrame(int requested_frame) throw(ReaderClosed);
tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(ReaderClosed);
/// Open the internal reader
void Open() throw(InvalidFile, ReaderClosed);
@@ -198,7 +198,7 @@ namespace openshot {
/// Get all properties for a specific frame (perfect for a UI to display the current state
/// of all properties at any time)
string PropertiesJSON(int requested_frame);
string PropertiesJSON(long int requested_frame);
/// @brief Remove an effect from the clip
/// @param effect Remove an effect from the clip.

View File

@@ -92,7 +92,7 @@ namespace openshot {
/// Get all properties for a specific frame (perfect for a UI to display the current state
/// of all properties at any time)
virtual string PropertiesJSON(int requested_frame) = 0;
virtual string PropertiesJSON(long int requested_frame) = 0;
};

View File

@@ -60,7 +60,7 @@ namespace openshot {
Color(Keyframe Red, Keyframe Green, Keyframe Blue, Keyframe Alpha);
/// Get the HEX value of a color at a specific frame
string GetColorHex(int frame_number);
string GetColorHex(long int frame_number);
/// Get the distance between 2 RGB pairs. (0=identical colors, 10=very close colors, 760=very different colors)
static long GetDistance(long R1, long G1, long B1, long R2, long G2, long B2);

View File

@@ -93,7 +93,7 @@ public:
virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame*, IDeckLinkAudioInputPacket*);
// Extra methods
tr1::shared_ptr<openshot::Frame> GetFrame(int requested_frame);
tr1::shared_ptr<openshot::Frame> GetFrame(long int requested_frame);
unsigned long GetCurrentFrameNumber();
private:

View File

@@ -108,7 +108,7 @@ namespace openshot
///
/// @returns The requested frame (containing the image)
/// @param requested_frame The frame number that is requested.
tr1::shared_ptr<Frame> GetFrame(int requested_frame) throw(ReaderClosed);
tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(ReaderClosed);
unsigned long GetCurrentFrameNumber();
/// Determine if reader is open or closed

View File

@@ -76,7 +76,7 @@ namespace openshot
///
/// @returns The requested frame (containing the image)
/// @param requested_frame The frame number that is requested.
tr1::shared_ptr<Frame> GetFrame(int requested_frame) throw(ReaderClosed);
tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(ReaderClosed);
/// Determine if reader is open or closed
bool IsOpen() { return is_open; };

View File

@@ -84,7 +84,7 @@ namespace openshot
/// @returns The modified openshot::Frame object
/// @param frame The frame object that needs the effect applied to it
/// @param frame_number The frame number (starting at 1) of the effect on the timeline.
virtual tr1::shared_ptr<Frame> GetFrame(tr1::shared_ptr<Frame> frame, int frame_number) = 0;
virtual tr1::shared_ptr<Frame> GetFrame(tr1::shared_ptr<Frame> frame, long int frame_number) = 0;
/// Initialize the values of the EffectInfo struct. It is important for derived classes to call
/// this method, or the EffectInfo struct values will not be initialized.

View File

@@ -106,38 +106,43 @@ namespace openshot
bool is_duration_known;
bool check_interlace;
bool check_fps;
bool has_missing_frames;
int num_of_rescalers;
int rescaler_position;
vector<SwsContext*> image_rescalers;
Cache working_cache;
Cache missing_frames;
map<AVPacket*, AVPacket*> packets;
map<AVPicture*, AVPicture*> frames;
map<int, int> processing_video_frames;
multimap<int, int> processing_audio_frames;
map<int, int> processed_video_frames;
map<int, int> processed_audio_frames;
map<long int, long int> processing_video_frames;
multimap<long int, long int> processing_audio_frames;
map<long int, long int> processed_video_frames;
map<long int, long int> processed_audio_frames;
multimap<long int, long int> missing_video_frames;
multimap<long int, long int> duplicate_video_frames;
AudioLocation previous_packet_location;
// DEBUG VARIABLES (FOR AUDIO ISSUES)
int prev_samples;
int prev_pts;
int pts_total;
int pts_counter;
long int prev_pts;
long int pts_total;
long int pts_counter;
bool is_seeking;
int seeking_pts;
int seeking_frame;
long int seeking_pts;
long int seeking_frame;
bool is_video_seek;
int seek_count;
int seek_audio_frame_found;
int seek_video_frame_found;
long int seek_audio_frame_found;
long int seek_video_frame_found;
int audio_pts_offset;
int video_pts_offset;
int last_frame;
int largest_frame_processed;
long int audio_pts_offset;
long int video_pts_offset;
long int last_frame;
long int largest_frame_processed;
long int 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();
@@ -145,26 +150,29 @@ namespace openshot
/// 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(long int requested_frame);
/// Check the working queue, and move finished frames to the finished queue
void CheckWorkingFrames(bool end_of_stream);
void CheckWorkingFrames(bool end_of_stream, long int requested_frame);
/// Convert image to RGB format
void convert_image(int current_frame, AVPicture *copyFrame, int width, int height, PixelFormat pix_fmt);
void convert_image(long int current_frame, AVPicture *copyFrame, int width, int height, PixelFormat pix_fmt);
/// Convert Frame Number into Audio PTS
int ConvertFrameToAudioPTS(int frame_number);
long int ConvertFrameToAudioPTS(long int frame_number);
/// Convert Frame Number into Video PTS
int ConvertFrameToVideoPTS(int frame_number);
long int ConvertFrameToVideoPTS(long int frame_number);
/// Convert Video PTS into Frame Number
int ConvertVideoPTStoFrame(int pts);
long int ConvertVideoPTStoFrame(long int pts);
/// Create a new Frame (or return an existing one) and add it to the working queue.
tr1::shared_ptr<Frame> CreateFrame(int requested_frame);
tr1::shared_ptr<Frame> CreateFrame(long int requested_frame);
/// Calculate Starting video frame and sample # for an audio PTS
AudioLocation GetAudioPTSLocation(int pts);
AudioLocation GetAudioPTSLocation(long int pts);
/// Get an AVFrame (if any)
bool GetAVFrame();
@@ -173,28 +181,28 @@ namespace openshot
int GetNextPacket();
/// Get the smallest video frame that is still being processed
int GetSmallestVideoFrame();
long int GetSmallestVideoFrame();
/// Get the smallest audio frame that is still being processed
int GetSmallestAudioFrame();
long int GetSmallestAudioFrame();
/// Get the PTS for the current video packet
int GetVideoPTS();
long int GetVideoPTS();
/// Init a collection of software rescalers (thread safe)
void InitScalers();
/// Remove partial frames due to seek
bool IsPartialFrame(int requested_frame);
bool IsPartialFrame(long int requested_frame);
/// Process a video packet
void ProcessVideoPacket(int requested_frame);
void ProcessVideoPacket(long int requested_frame);
/// Process an audio packet
void ProcessAudioPacket(int requested_frame, int target_frame, int starting_sample);
void ProcessAudioPacket(long int requested_frame, long int target_frame, int starting_sample);
/// Read the stream until we find the requested Frame
tr1::shared_ptr<Frame> ReadStream(int requested_frame);
tr1::shared_ptr<Frame> ReadStream(long int requested_frame);
/// Remove AVFrame from cache (and deallocate it's memory)
void RemoveAVFrame(AVPicture*);
@@ -206,7 +214,7 @@ namespace openshot
void RemoveScalers();
/// Seek to a specific Frame. This is not always frame accurate, it's more of an estimation on many codecs.
void Seek(int requested_frame) throw(TooManySeeks);
void Seek(long int requested_frame) throw(TooManySeeks);
/// Update PTS Offset (if any)
void UpdatePTSOffset(bool is_video);
@@ -239,7 +247,7 @@ namespace openshot
///
/// @returns The requested frame of video
/// @param requested_frame The frame number that is requested.
tr1::shared_ptr<Frame> GetFrame(int requested_frame) throw(OutOfBoundsFrame, ReaderClosed, TooManySeeks);
tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(OutOfBoundsFrame, ReaderClosed, TooManySeeks);
/// Determine if reader is open or closed
bool IsOpen() { return is_open; };

View File

@@ -322,7 +322,7 @@ namespace openshot
/// @param reader A openshot::ReaderBase object which will provide frames to be written
/// @param start The starting frame number of the reader
/// @param length The number of frames to write
void WriteFrame(ReaderBase* reader, int start, int length) throw(WriterClosed);
void WriteFrame(ReaderBase* reader, long int start, long int length) throw(WriterClosed);
/// @brief Write the file trailer (after all frames are written). This is called automatically
/// by the Close() method if this method has not yet been called.

View File

@@ -129,22 +129,22 @@ namespace openshot
int sample_rate;
public:
int number; ///< This is the frame number (starting at 1)
long int number; ///< This is the frame number (starting at 1)
/// Constructor - blank frame (300x200 blank image, 48kHz audio silence)
Frame();
/// Constructor - image only (48kHz audio silence)
Frame(int number, int width, int height, string color);
Frame(long int number, int width, int height, string color);
/// Constructor - image only from pixel array (48kHz audio silence)
Frame(int number, int width, int height, const string map, const Magick::StorageType type, const void *pixels_);
Frame(long int number, int width, int height, const string map, const Magick::StorageType type, const void *pixels_);
/// Constructor - audio only (300x200 blank image)
Frame(int number, int samples, int channels);
Frame(long int number, int samples, int channels);
/// Constructor - image & audio
Frame(int number, int width, int height, string color, int samples, int channels);
Frame(long int number, int width, int height, string color, int samples, int channels);
/// Copy constructor
Frame ( const Frame &other );
@@ -243,7 +243,7 @@ namespace openshot
int GetSamplesPerFrame(Fraction fps, int sample_rate, int channels);
/// Calculate the # of samples per video frame (for a specific frame number and frame rate)
static int GetSamplesPerFrame(int frame_number, Fraction fps, int sample_rate, int channels);
static int GetSamplesPerFrame(long int frame_number, Fraction fps, int sample_rate, int channels);
/// Get an audio waveform image
tr1::shared_ptr<QImage> GetWaveform(int width, int height, int Red, int Green, int Blue, int Alpha);

View File

@@ -72,12 +72,12 @@ namespace openshot
*/
struct Field
{
int Frame;
long int Frame;
bool isOdd;
Field() : Frame(0), isOdd(true) { };
Field(int frame, bool isodd)
Field(long int frame, bool isodd)
{
Frame = frame;
isOdd = isodd;
@@ -149,7 +149,7 @@ namespace openshot
AVAudioResampleContext *avr; // Audio resampling context object
// Internal methods used by init
void AddField(int frame);
void AddField(long int frame);
void AddField(Field field);
// Use the original and target frame rates and a pull-down technique to create
@@ -173,7 +173,7 @@ namespace openshot
void Close();
/// Get a frame based on the target frame rate and the new frame number of a frame
MappedFrame GetMappedFrame(int TargetFrameNumber) throw(OutOfBoundsFrame);
MappedFrame GetMappedFrame(long int TargetFrameNumber) throw(OutOfBoundsFrame);
/// Get the cache object used by this reader
Cache* GetCache() { return &final_cache; };
@@ -184,7 +184,7 @@ namespace openshot
///
/// @returns The requested frame of video
/// @param requested_frame The frame number that is requested.
tr1::shared_ptr<Frame> GetFrame(int requested_frame) throw(ReaderClosed);
tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(ReaderClosed);
/// Determine if reader is open or closed
bool IsOpen();
@@ -202,7 +202,7 @@ namespace openshot
void PrintMapping();
/// Resample audio and map channels (if needed)
void ResampleMappedAudio(tr1::shared_ptr<Frame> frame, int original_frame_number);
void ResampleMappedAudio(tr1::shared_ptr<Frame> frame, long int original_frame_number);
};
}

View File

@@ -88,7 +88,7 @@ namespace openshot
///
/// @returns The requested frame (containing the image)
/// @param requested_frame The frame number that is requested.
tr1::shared_ptr<Frame> GetFrame(int requested_frame) throw(ReaderClosed);
tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(ReaderClosed);
/// Determine if reader is open or closed
bool IsOpen() { return is_open; };

View File

@@ -140,7 +140,7 @@ namespace openshot
/// @param reader A openshot::ReaderBase object which will provide frames to be written
/// @param start The starting frame number of the reader
/// @param length The number of frames to write
void WriteFrame(ReaderBase* reader, int start, int length) throw(WriterClosed);
void WriteFrame(ReaderBase* reader, long int start, long int length) throw(WriterClosed);
};

View File

@@ -80,13 +80,13 @@ namespace openshot {
void CreateFactorialTable();
// Get a factorial for a coordinate
double Factorial(int n);
double Factorial(long int n);
// Calculate the factorial function for Bernstein basis
double Ni(int n, int i);
double Ni(long int n, long int i);
// Calculate Bernstein Basis
double Bernstein(int n, int i, double t);
double Bernstein(long int n, long int i, double t);
public:
vector<Point> Points; ///< Vector of all Points
@@ -118,31 +118,34 @@ namespace openshot {
void FlipPoints();
/// Get the index of a point by matching a coordinate
int FindIndex(Point p) throw(OutOfBoundsPoint);
long int FindIndex(Point p) throw(OutOfBoundsPoint);
/// Get the value at a specific index
float GetValue(int index);
float GetValue(long int index);
/// Get the rounded INT value at a specific index
int GetInt(int index);
int GetInt(long int index);
/// Get the rounded LONG value at a specific index
long int GetLong(long int index);
/// Get the fraction that represents how many times this value is repeated in the curve
Fraction GetRepeatFraction(int index);
Fraction GetRepeatFraction(long int index);
/// Get the change in Y value (from the previous Y value)
float GetDelta(int index);
float GetDelta(long int index);
/// Get a point at a specific index
Point& GetPoint(int index) throw(OutOfBoundsPoint);
Point& GetPoint(long int index) throw(OutOfBoundsPoint);
/// Get current point (or closest point) from the X coordinate (i.e. the frame number)
Point GetClosestPoint(Point p);
// Get the number of values (i.e. coordinates on the X axis)
int GetLength();
long int GetLength();
/// Get the number of points (i.e. # of points)
int GetCount();
long int GetCount();
/// Get the direction of the curve at a specific index (increasing or decreasing)
bool IsIncreasing(int index);
@@ -165,14 +168,14 @@ namespace openshot {
void RemovePoint(Point p) throw(OutOfBoundsPoint);
/// Remove a point by index
void RemovePoint(int index) throw(OutOfBoundsPoint);
void RemovePoint(long int index) throw(OutOfBoundsPoint);
/// Scale all points by a percentage (good for evenly lengthening or shortening an openshot::Keyframe)
/// 1.0 = same size, 1.05 = 5% increase, etc...
void ScalePoints(float scale);
/// Replace an existing point with a new point
void UpdatePoint(int index, Point p);
void UpdatePoint(long int index, Point p);
/// Print a list of points
void PrintPoints();

View File

@@ -90,7 +90,7 @@ namespace openshot
///
/// @returns The requested frame (containing the image)
/// @param requested_frame The frame number that is requested.
tr1::shared_ptr<Frame> GetFrame(int requested_frame) throw(ReaderClosed);
tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(ReaderClosed);
/// Determine if reader is open or closed
bool IsOpen() { return is_open; };

View File

@@ -140,7 +140,7 @@ namespace openshot
///
/// @returns The requested frame of video
/// @param[in] number The frame number that is requested.
virtual tr1::shared_ptr<Frame> GetFrame(int number) = 0;
virtual tr1::shared_ptr<Frame> GetFrame(long int number) = 0;
/// A thread safe version of GetFrame.
//tr1::shared_ptr<Frame> GetFrameSafe(int number);

View File

@@ -124,7 +124,7 @@ namespace openshot
///
/// @returns The requested frame (containing the image)
/// @param requested_frame The frame number that is requested.
tr1::shared_ptr<Frame> GetFrame(int requested_frame) throw(ReaderClosed);
tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(ReaderClosed);
/// Determine if reader is open or closed
bool IsOpen() { return is_open; };

View File

@@ -150,7 +150,7 @@ namespace openshot {
Cache final_cache; ///<Final cache of timeline frames
/// Process a new layer of video or audio
void add_layer(tr1::shared_ptr<Frame> new_frame, Clip* source_clip, int clip_frame_number, int timeline_frame_number, bool is_top_clip);
void add_layer(tr1::shared_ptr<Frame> new_frame, Clip* source_clip, long int clip_frame_number, long int timeline_frame_number, bool is_top_clip);
/// Apply a FrameMapper to a clip which matches the settings of this timeline
void apply_mapper_to_clip(Clip* clip);
@@ -162,7 +162,7 @@ namespace openshot {
void apply_json_to_timeline(Json::Value change) throw(InvalidJSONKey); ///<Apply JSON diff to timeline properties
/// Calculate time of a frame number, based on a framerate
float calculate_time(int number, Fraction rate);
float calculate_time(long int number, Fraction rate);
/// Find intersecting (or non-intersecting) openshot::Clip objects
///
@@ -170,10 +170,10 @@ namespace openshot {
/// @param requested_frame The frame number that is requested.
/// @param number_of_frames The number of frames to check
/// @param include Include or Exclude intersecting clips
vector<Clip*> find_intersecting_clips(int requested_frame, int number_of_frames, bool include);
vector<Clip*> find_intersecting_clips(long int requested_frame, int number_of_frames, bool include);
/// Apply effects to the source frame (if any)
tr1::shared_ptr<Frame> apply_effects(tr1::shared_ptr<Frame> frame, int timeline_frame_number, int layer);
tr1::shared_ptr<Frame> apply_effects(tr1::shared_ptr<Frame> frame, long int timeline_frame_number, int layer);
/// Compare 2 floating point numbers for equality
bool isEqual(double a, double b);
@@ -231,7 +231,7 @@ namespace openshot {
///
/// @returns The requested frame (containing the image)
/// @param requested_frame The frame number that is requested.
tr1::shared_ptr<Frame> GetFrame(int requested_frame) throw(ReaderClosed, OutOfBoundsFrame);
tr1::shared_ptr<Frame> GetFrame(long int requested_frame) throw(ReaderClosed, OutOfBoundsFrame);
// Curves for the viewport
Keyframe viewport_scale; ///<Curve representing the scale of the viewport (0 to 100)

Some files were not shown because too many files have changed in this diff Show More