2011-10-11 08:44:27 -05:00
/**
2013-09-09 23:32:16 -05:00
* @ file
* @ brief Header file for Frame class
2013-09-12 17:52:10 -05:00
* @ author Jonathan Thomas < jonathan @ openshot . org >
*
* @ section LICENSE
*
2014-03-29 18:49:22 -05:00
* Copyright ( c ) 2008 - 2014 OpenShot Studios , LLC
* < http : //www.openshotstudios.com/>. This file is part of
* OpenShot Library ( libopenshot ) , an open - source project dedicated to
* delivering high quality video editing and animation solutions to the
* world . For more information visit < http : //www.openshot.org/>.
2013-09-12 17:52:10 -05:00
*
2014-03-29 18:49:22 -05:00
* OpenShot Library ( libopenshot ) is free software : you can redistribute it
2014-07-11 16:52:14 -05:00
* and / or modify it under the terms of the GNU Lesser General Public License
2014-03-29 18:49:22 -05:00
* as published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
2013-09-12 17:52:10 -05:00
*
2014-03-29 18:49:22 -05:00
* 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
2014-07-11 16:52:14 -05:00
* GNU Lesser General Public License for more details .
2013-09-12 17:52:10 -05:00
*
2014-07-11 16:52:14 -05:00
* You should have received a copy of the GNU Lesser General Public License
2014-03-29 18:49:22 -05:00
* along with OpenShot Library . If not , see < http : //www.gnu.org/licenses/>.
2011-10-11 08:44:27 -05:00
*/
2013-09-12 17:52:10 -05:00
# ifndef OPENSHOT_FRAME_H
# define OPENSHOT_FRAME_H
2011-10-11 08:44:27 -05:00
/// Do not include the juce unittest headers, because it collides with unittest++
2012-08-05 15:17:37 -05:00
# ifndef __JUCE_UNITTEST_JUCEHEADER__
# define __JUCE_UNITTEST_JUCEHEADER__
# endif
2013-06-09 01:08:23 -05:00
# ifndef _NDEBUG
// Define NO debug for JUCE on mac os
# define _NDEBUG
# endif
2011-10-11 08:44:27 -05:00
# include <iomanip>
# include <sstream>
# include <queue>
2016-02-23 00:27:03 -06:00
# include <QtWidgets/QApplication>
2015-03-16 13:59:11 -05:00
# include <QtGui/QImage>
2015-06-01 00:20:14 -07:00
# include <QtGui/QColor>
2016-02-23 00:27:03 -06:00
# include <QtGui/QBitmap>
2015-06-01 00:20:14 -07:00
# include <QtCore/QString>
# include <QtCore/QVector>
# include <QtGui/QPainter>
2016-02-23 00:27:03 -06:00
# include <QtWidgets/QHBoxLayout>
# include <QtWidgets/QWidget>
# include <QtWidgets/QLabel>
2012-10-17 09:57:02 -05:00
# include <tr1/memory>
2013-02-06 02:09:21 -06:00
# include <unistd.h>
2016-07-30 16:57:48 -05:00
# include "ZmqLogger.h"
2016-02-23 00:27:03 -06:00
# ifdef USE_IMAGEMAGICK
# include "Magick++.h"
# endif
2012-06-16 02:12:48 -05:00
# include "JuceLibraryCode/JuceHeader.h"
2015-02-05 00:11:55 -06:00
# include "ChannelLayouts.h"
2011-10-11 08:44:27 -05:00
# include "AudioBufferSource.h"
2012-08-05 15:17:37 -05:00
# include "AudioResampler.h"
2011-12-11 20:42:50 -06:00
# include "Fraction.h"
2011-10-11 08:44:27 -05:00
2015-03-16 13:59:11 -05:00
2011-10-11 08:44:27 -05:00
using namespace std ;
namespace openshot
{
/**
2013-09-09 23:32:16 -05:00
* @ brief This class represents a single frame of video ( i . e . image & audio data )
2011-10-11 08:44:27 -05:00
*
* FileReaders ( such as FFmpegReader ) use instances of this class to store the individual frames of video ,
2013-09-15 22:21:19 -05:00
* which include both the image data ( i . e . pixels ) and audio samples . An openshot : : Frame also has many debug
* methods , such as the ability to display the image ( using X11 ) , play the audio samples ( using JUCE ) , or
* display the audio waveform as an image .
*
* FileWriters ( such as FFmpegWriter ) use instances of this class to create new video files , image files , or
* video streams . So , think of these openshot : : Frame instances as the smallest unit of work in a video
* editor .
*
* There are many ways to create an instance of an openshot : : Frame :
* @ code
*
* // Most basic: a blank frame (300x200 blank image, 48kHz audio silence)
* Frame ( ) ;
*
* // Image only settings (48kHz audio silence)
* Frame ( 1 , // Frame number
* 720 , // Width of image
* 480 , // Height of image
* " #000000 " // HTML color code of background color
* ) ;
*
* // Audio only (300x200 blank image)
* Frame ( number , // Frame number
* 44100 , // Sample rate of audio stream
* 2 // Number of audio channels
* ) ;
*
* // Image and Audio settings (user defines all key settings)
* Frame ( number , // Frame number
* 720 , // Width of image
* 480 , // Height of image
* " #000000 " // HTML color code of background color
* 44100 , // Sample rate of audio stream
* 2 // Number of audio channels
* ) ;
*
* // Some methods require a shared pointer to an openshot::Frame object.
* tr1 : : shared_ptr < Frame > f ( new Frame ( 1 , 720 , 480 , " #000000 " , 44100 , 2 ) ) ;
*
* @ endcode
2011-10-11 08:44:27 -05:00
*/
class Frame
{
private :
2015-06-01 00:20:14 -07:00
tr1 : : shared_ptr < QImage > image ;
tr1 : : shared_ptr < QImage > wave_image ;
2012-10-17 09:57:02 -05:00
tr1 : : shared_ptr < juce : : AudioSampleBuffer > audio ;
2016-02-23 00:27:03 -06:00
tr1 : : shared_ptr < QApplication > previewApp ;
2016-03-08 00:38:06 -06:00
CriticalSection addingImageSection ;
2015-06-01 00:20:14 -07:00
const unsigned char * qbuffer ;
2011-12-11 20:42:50 -06:00
Fraction pixel_ratio ;
2012-07-02 00:51:10 -05:00
int channels ;
2015-02-05 00:11:55 -06:00
ChannelLayout channel_layout ;
2012-10-26 00:27:44 -05:00
int width ;
int height ;
2015-02-05 00:11:55 -06:00
int sample_rate ;
2012-07-02 00:51:10 -05:00
2016-02-23 00:27:03 -06:00
/// Constrain a color value from 0 to 255
int constrain ( int color_value ) ;
2011-10-11 08:44:27 -05:00
public :
2016-01-05 01:59:50 -06:00
long int number ; ///< This is the frame number (starting at 1)
bool has_audio_data ; ///< This frame has been loaded with audio data
bool has_image_data ; ///< This frame has been loaded with pixel data
2011-10-11 08:44:27 -05:00
/// Constructor - blank frame (300x200 blank image, 48kHz audio silence)
Frame ( ) ;
/// Constructor - image only (48kHz audio silence)
2015-08-24 01:05:48 -05:00
Frame ( long int number , int width , int height , string color ) ;
2011-10-11 08:44:27 -05:00
/// Constructor - audio only (300x200 blank image)
2015-08-24 01:05:48 -05:00
Frame ( long int number , int samples , int channels ) ;
2011-10-11 08:44:27 -05:00
/// Constructor - image & audio
2015-08-24 01:05:48 -05:00
Frame ( long int number , int width , int height , string color , int samples , int channels ) ;
2011-10-11 08:44:27 -05:00
/// Copy constructor
Frame ( const Frame & other ) ;
/// Assignment operator
2013-01-12 12:45:55 -06:00
//Frame& operator= (const Frame& other);
/// Destructor
~ Frame ( ) ;
2011-10-11 08:44:27 -05:00
2012-10-12 00:54:53 -05:00
/// Add (or replace) pixel data to the frame (based on a solid color)
2016-09-07 00:40:01 -05:00
void AddColor ( int new_width , int new_height , string color ) ;
2012-10-12 00:54:53 -05:00
2012-08-11 21:13:05 -05:00
/// Add (or replace) pixel data to the frame
2016-09-07 00:40:01 -05:00
void AddImage ( int new_width , int new_height , int bytes_per_pixel , QImage : : Format type , const unsigned char * pixels_ ) ;
2012-08-11 21:13:05 -05:00
2012-08-29 15:29:15 -05:00
/// Add (or replace) pixel data to the frame
2015-06-01 00:20:14 -07:00
void AddImage ( tr1 : : shared_ptr < QImage > new_image ) ;
2012-08-29 15:29:15 -05:00
2012-10-18 02:58:09 -05:00
/// Add (or replace) pixel data to the frame (for only the odd or even lines)
2015-06-01 00:20:14 -07:00
void AddImage ( tr1 : : shared_ptr < QImage > new_image , bool only_odd_lines ) ;
2016-02-23 00:27:03 -06:00
# ifdef USE_IMAGEMAGICK
2015-06-01 00:20:14 -07:00
/// Add (or replace) pixel data to the frame from an ImageMagick Image
void AddMagickImage ( tr1 : : shared_ptr < Magick : : Image > new_image ) ;
2016-02-23 00:27:03 -06:00
# endif
2012-10-18 02:58:09 -05:00
2012-08-11 21:13:05 -05:00
/// Add audio samples to a specific channel
2012-11-29 16:32:48 -06:00
void AddAudio ( bool replaceSamples , int destChannel , int destStartSample , const float * source , int numSamples , float gainToApplyToSource ) ;
2015-08-02 20:32:33 -05:00
/// Add audio silence
void AddAudioSilence ( int numSamples ) ;
2012-11-29 16:32:48 -06:00
/// Apply gain ramp (i.e. fading volume)
void ApplyGainRamp ( int destChannel , int destStartSample , int numSamples , float initial_gain , float final_gain ) ;
2012-08-11 21:13:05 -05:00
2015-02-05 00:11:55 -06:00
/// Channel Layout of audio samples. A frame needs to keep track of this, since Writers do not always
/// know the original channel layout of a frame's audio samples (i.e. mono, stereo, 5 point surround, etc...)
ChannelLayout ChannelsLayout ( ) ;
// Set the channel layout of audio samples (i.e. mono, stereo, 5 point surround, etc...)
void ChannelsLayout ( ChannelLayout new_channel_layout ) { channel_layout = new_channel_layout ; } ;
2015-06-01 00:20:14 -07:00
/// Clean up buffer after QImage is deleted
static void cleanUpBuffer ( void * info ) ;
2012-08-22 17:31:12 -05:00
/// Clear the waveform image (and deallocate it's memory)
void ClearWaveform ( ) ;
2011-10-11 08:44:27 -05:00
/// Copy data and pointers from another Frame instance
void DeepCopy ( const Frame & other ) ;
/// Display the frame image to the screen (primarily used for debugging reasons)
void Display ( ) ;
2011-10-24 17:32:26 -05:00
/// Display the wave form
2012-08-22 17:31:12 -05:00
void DisplayWaveform ( ) ;
2011-10-24 17:32:26 -05:00
2016-04-22 02:43:06 -05:00
/// Get magnitude of range of samples (if channel is -1, return average of all channels for that sample)
float GetAudioSample ( int channel , int sample , int magnitude_range ) ;
2012-07-09 01:22:11 -05:00
/// Get an array of sample data
float * GetAudioSamples ( int channel ) ;
2012-07-30 02:37:19 -05:00
/// Get an array of sample data (all channels interleaved together), using any sample rate
2015-02-05 00:11:55 -06:00
float * GetInterleavedAudioSamples ( int new_sample_rate , AudioResampler * resampler , int * sample_count ) ;
// Get a planar array of sample data, using any sample rate
float * GetPlanarAudioSamples ( int new_sample_rate , AudioResampler * resampler , int * sample_count ) ;
2012-07-24 12:50:17 -05:00
2012-07-09 01:22:11 -05:00
/// Get number of audio channels
int GetAudioChannelsCount ( ) ;
2016-04-22 02:43:06 -05:00
/// Get number of audio samples
2012-07-09 01:22:11 -05:00
int GetAudioSamplesCount ( ) ;
2014-01-27 19:03:46 +08:00
juce : : AudioSampleBuffer * GetAudioSampleBuffer ( ) ;
2012-10-11 17:30:32 -05:00
/// Get the size in bytes of this frame (rough estimate)
int64 GetBytes ( ) ;
2015-06-01 00:20:14 -07:00
/// Get pointer to Qt QImage image object
tr1 : : shared_ptr < QImage > GetImage ( ) ;
2012-08-29 16:07:47 -05:00
2016-02-23 00:27:03 -06:00
# ifdef USE_IMAGEMAGICK
2015-06-01 00:20:14 -07:00
/// Get pointer to ImageMagick image object
tr1 : : shared_ptr < Magick : : Image > GetMagickImage ( ) ;
2016-02-23 00:27:03 -06:00
# endif
2015-03-16 13:59:11 -05:00
2015-02-05 00:11:55 -06:00
/// Set Pixel Aspect Ratio
Fraction GetPixelRatio ( ) { return pixel_ratio ; } ;
2011-10-11 08:44:27 -05:00
/// Get pixel data (as packets)
2015-06-01 00:20:14 -07:00
const unsigned char * GetPixels ( ) ;
2011-10-11 08:44:27 -05:00
/// Get pixel data (for only a single scan-line)
2015-06-01 00:20:14 -07:00
const unsigned char * GetPixels ( int row ) ;
2011-10-11 08:44:27 -05:00
/// Get height of image
int GetHeight ( ) ;
2014-01-28 17:17:38 -06:00
/// Calculate the # of samples per video frame (for the current frame number)
2015-03-08 21:42:53 -05:00
int GetSamplesPerFrame ( Fraction fps , int sample_rate , int channels ) ;
2014-01-28 17:17:38 -06:00
/// Calculate the # of samples per video frame (for a specific frame number and frame rate)
2015-08-24 01:05:48 -05:00
static int GetSamplesPerFrame ( long int frame_number , Fraction fps , int sample_rate , int channels ) ;
2014-01-28 17:17:38 -06:00
2012-08-22 17:31:12 -05:00
/// Get an audio waveform image
2015-06-01 00:20:14 -07:00
tr1 : : shared_ptr < QImage > GetWaveform ( int width , int height , int Red , int Green , int Blue , int Alpha ) ;
2012-08-22 17:31:12 -05:00
/// Get an audio waveform image pixels
2015-06-01 00:20:14 -07:00
const unsigned char * GetWaveformPixels ( int width , int height , int Red , int Green , int Blue , int Alpha ) ;
2012-08-22 17:31:12 -05:00
2011-10-11 08:44:27 -05:00
/// Get height of image
int GetWidth ( ) ;
2015-03-01 22:36:39 -06:00
/// Resize audio container to hold more (or less) samples and channels
void ResizeAudio ( int channels , int length , int sample_rate , ChannelLayout channel_layout ) ;
2015-02-05 00:11:55 -06:00
/// Get the original sample rate of this frame's audio data
int SampleRate ( ) ;
/// Set the original sample rate of this frame's audio data
void SampleRate ( int orig_sample_rate ) { sample_rate = orig_sample_rate ; } ;
2016-02-23 00:27:03 -06:00
/// Save the frame image to the specified path. The image format can be BMP, JPG, JPEG, PNG, PPM, XBM, XPM
void Save ( string path , float scale , string format = " PNG " , int quality = 100 ) ;
2011-10-11 08:44:27 -05:00
2013-02-10 21:16:46 -06:00
/// Set frame number
void SetFrameNumber ( int number ) ;
2012-08-11 21:13:05 -05:00
/// Set Pixel Aspect Ratio
void SetPixelRatio ( int num , int den ) ;
2011-10-24 08:22:21 -05:00
2014-05-20 00:57:27 -05:00
/// Thumbnail the frame image with tons of options to the specified path. The image format is determined from the extension (i.e. image.PNG, image.JPEG).
/// This method allows for masks, overlays, background color, and much more accurate resizing (including padding and centering)
void Thumbnail ( string path , int new_width , int new_height , string mask_path , string overlay_path ,
2016-02-23 00:27:03 -06:00
string background_color , bool ignore_aspect , string format = " png " , int quality = 100 ) throw ( InvalidFile ) ;
2014-05-20 00:57:27 -05:00
2011-10-11 08:44:27 -05:00
/// Play audio samples for this frame
2015-02-05 00:11:55 -06:00
void Play ( ) ;
2011-10-11 08:44:27 -05:00
} ;
}
# endif