filmstro_ffmpeg
 All Classes Files Functions Friends Macros
filmstro_ffmpeg_FFmpegVideoReader.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3  Copyright (c) 2017, Filmstro Ltd. - Daniel Walz
4  All rights reserved.
5 
6  Redistribution and use in source and binary forms, with or without modification,
7  are permitted provided that the following conditions are met:
8  1. Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10  2. Redistributions in binary form must reproduce the above copyright notice,
11  this list of conditions and the following disclaimer in the documentation
12  and/or other materials provided with the distribution.
13  3. Neither the name of the copyright holder nor the names of its contributors
14  may be used to endorse or promote products derived from this software without
15  specific prior written permission.
16 
17  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26  OF THE POSSIBILITY OF SUCH DAMAGE.
27  ==============================================================================
28  \class FFmpegVideoReader
29  \file filmstro_ffmpeg_FFmpegVideoReader.h
30  \brief A component to view a video decoded by FFmpeg
31 
32  \author Daniel Walz @ filmstro.com
33  \date August 31st 2016
34 
35  \description This class will read a video file using ffmpeg
36 
37  ==============================================================================
38  */
39 
40 
41 #ifndef FILMSTRO_FFMPEG_FFMPEGVIDEOREADER_H_INCLUDED
42 #define FILMSTRO_FFMPEG_FFMPEGVIDEOREADER_H_INCLUDED
43 
44 #include <atomic>
45 
55 class FFmpegVideoReader : public juce::PositionableAudioSource
56 {
57 public:
58 
62  FFmpegVideoReader (const int audioFifoSize=192000, const int videoFifoSize=20);
63  virtual ~FFmpegVideoReader();
64 
65  // ==============================================================================
66  // video decoder thread
67  // ==============================================================================
73  class DecoderThread : public juce::Thread
74  {
75  public:
76  DecoderThread (AudioBufferFIFO<float>& fifo, const int videoFifoSize);
77 
78  virtual ~DecoderThread ();
79 
80  bool loadMovieFile (const juce::File& inputFile);
81 
82  void closeMovieFile ();
83 
84  void addVideoListener (FFmpegVideoListener* listener);
85 
87 
89  void run() override;
90 
92  void setCurrentPTS (const double pts, bool seek = false);
93 
95  double getCurrentPTS () const;
96 
98  int getVideoWidth () const;
99 
101  int getVideoHeight () const;
102 
105  enum AVPixelFormat getPixelFormat () const;
106 
108  double getPixelAspect () const;
109 
110  enum AVSampleFormat getSampleFormat () const;
111 
114  double getFramesPerSecond () const;
115 
117  AVRational getVideoTimeBase () const;
118 
120  AVFormatContext* getVideoReaderContext();
121 
122  double getSampleRate () const;
123 
124  double getDuration () const;
125 
126  int getNumChannels () const;
127 
128  AVCodecContext* getVideoContext () const;
129  AVCodecContext* getAudioContext () const;
130  AVCodecContext* getSubtitleContext () const;
131 
132  private:
133 
134  int openCodecContext (AVCodecContext** decoderContext,
135  enum AVMediaType type,
136  bool refCounted);
137 
139  int decodeAudioPacket (AVPacket packet);
140 
142  double decodeVideoPacket (AVPacket packet);
143 
144 
145  // ==============================================================================
146 
147 
149  AudioBufferFIFO<float>& audioFifo;
150 
151  juce::WaitableEvent waitForPacket;
152 
154  std::vector<std::pair<double, AVFrame*> > videoFrames;
155  std::atomic<int> videoFifoRead;
156  std::atomic<int> videoFifoWrite;
157 
158  AVFormatContext* formatContext;
159  AVCodecContext* videoContext;
160  AVCodecContext* audioContext;
161  AVCodecContext* subtitleContext;
162 
163  int videoStreamIdx;
164  int audioStreamIdx;
165  int subtitleStreamIdx;
166 
167  AVFrame* audioFrame;
168 
169  std::atomic<double> currentPTS;
170 
171  juce::ListenerList<FFmpegVideoListener> videoListeners;
172 
174  juce::AudioBuffer<float> buffer;
175 
176  };
177 
178  // ==============================================================================
179  // video methods
180  // ==============================================================================
181 
182  bool loadMovieFile (const juce::File& inputFile);
183 
184  void closeMovieFile ();
185 
187  juce::File getVideoFileName () const;
188 
191  double getFramesPerSecond () const;
192 
194  double getCurrentTimeStamp() const;
195 
197  double getVideoDuration () const;
198 
202  int getVideoSamplingRate () const;
203 
206  int getVideoChannels () const;
207 
210  enum AVSampleFormat getSampleFormat () const;
211 
214  void addVideoListener (FFmpegVideoListener* listener);
215 
217  void removeVideoListener (FFmpegVideoListener* listener);
218 
219  double getLastVideoPTS () const;
220 
222  int getVideoWidth () const;
223 
225  int getVideoHeight () const;
226 
228  double getVideoAspectRatio () const;
229 
231  double getVideoPixelAspect () const;
232 
235  enum AVPixelFormat getPixelFormat () const;
236 
238  AVRational getVideoTimeBase () const;
239 
240  static juce::String formatTimeCode (const double tc);
241 
242 
243  // ==============================================================================
244  // from PositionableAudioSource
245  // ==============================================================================
246 
247  void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override;
248 
249  void releaseResources () override;
250 
252  void getNextAudioBlock (const juce::AudioSourceChannelInfo &bufferToFill) override;
253 
255  bool waitForNextAudioBlockReady (const juce::AudioSourceChannelInfo &bufferToFill, const int msecs) const;
256 
258  void setNextReadPosition (juce::int64 newPosition) override;
259 
261  juce::int64 getNextReadPosition () const override;
262 
265  juce::int64 getTotalLength () const override;
266 
268  bool isLooping() const override;
269 
271  void setLooping (bool shouldLoop) override;
272 
273  // ==============================================================================
274  // FFmpeg low level
275  // ==============================================================================
276 
277  AVCodecContext* getVideoContext () const;
278  AVCodecContext* getAudioContext () const;
279  AVCodecContext* getSubtitleContext () const;
280 
281 
282  // ==============================================================================
283 private:
284 
285  juce::File videoFileName;
286 
287  bool fileReadyToRead;
288 
289  bool looping;
290 
291  int sampleRate;
292 
293  double framesPerSec;
294 
295  double resampleFactor;
296 
297  double currentTimeStamp;
298 
299  juce::int64 nextReadPos;
300 
301  AudioBufferFIFO<float> audioFifo;
302 
303  DecoderThread decoder;
304 
305  // use WeakReference so that removing a source doesn't lead to disaster
306  juce::WeakReference<FFmpegVideoReader>::Master masterReference;
307  friend class juce::WeakReference<FFmpegVideoReader>;
308 
309  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FFmpegVideoReader)
310 };
311 
312 #endif /* FILMSTRO_FFMPEG_FFMPEGVIDEOREADER_H_INCLUDED */
313 
void addVideoListener(FFmpegVideoListener *listener)
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:410
int getVideoSamplingRate() const
returns the sampling rate as specified in the video file.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:119
void releaseResources() override
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:217
juce::int64 getTotalLength() const override
Returns the total length in samples.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:273
bool waitForNextAudioBlockReady(const juce::AudioSourceChannelInfo &bufferToFill, const int msecs) const
Wait until the decoder thread has finished enough data.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:250
double getFramesPerSecond() const
Return the framerate.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:102
void removeVideoListener(FFmpegVideoListener *listener)
remove a video listener
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:143
AVCodecContext * getSubtitleContext() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:302
AVCodecContext * getAudioContext() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:298
DecoderThread(AudioBufferFIFO< float > &fifo, const int videoFifoSize)
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:311
int getVideoHeight() const
get the height of the video images according to decoder
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:662
virtual ~FFmpegVideoReader()
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:65
enum AVSampleFormat getSampleFormat() const
returns the audio sample format in the video file.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:170
void setCurrentPTS(const double pts, bool seek=false)
set the currently played PTS according to the audio stream
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:603
double getVideoDuration() const
returns the duration of the video in seconds according to the container context
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:114
void getNextAudioBlock(const juce::AudioSourceChannelInfo &bufferToFill) override
decodes packets to fill the audioFifo.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:222
Reads a ffmpeg video file
Definition: filmstro_ffmpeg_FFmpegVideoReader.h:55
double getPixelAspect() const
This will return the aspect ratio of each pixel.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:684
FFmpegVideoReader(const int audioFifoSize=192000, const int videoFifoSize=20)
Constructs a FFmpegVideoReader.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:54
AVCodecContext * getVideoContext() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:739
AVFormatContext * getVideoReaderContext()
Give access to the context to set up writers.
void closeMovieFile()
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:391
class for FFmpegReader to decode audio and images asynchronously This is to keep the audio thread as ...
Definition: filmstro_ffmpeg_FFmpegVideoReader.h:73
void setLooping(bool shouldLoop) override
Tells the source whether you'd like it to play in a loop.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:285
int getVideoWidth() const
get the width of the video images according to decoder
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:654
void setNextReadPosition(juce::int64 newPosition) override
Seeks in the stream.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:259
AVCodecContext * getSubtitleContext() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:747
Definition: filmstro_ffmpeg_FFmpegVideoListener.h:44
enum AVPixelFormat getPixelFormat() const
get the pixel format of the video images according to decoder, will be converted to BGR0 to be displa...
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:175
double getVideoAspectRatio() const
returns the aspect ratio video frame
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:158
int getVideoHeight() const
get the height of the video images according to decoder
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:153
AVRational getVideoTimeBase() const
This will return the time_base from the video stream.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:180
void run() override
working loop
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:560
double getCurrentPTS() const
returns the presentation timestamp the video is synchronised to
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:649
AVRational getVideoTimeBase() const
This will return the time_base from the video stream.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:691
bool loadMovieFile(const juce::File &inputFile)
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:76
bool isLooping() const override
Returns true if this source is actually playing in a loop.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:279
static juce::String formatTimeCode(const double tc)
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:185
double getCurrentTimeStamp() const
Get current presentation timecode according to audio stream.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:107
AVCodecContext * getVideoContext() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:294
bool loadMovieFile(const juce::File &inputFile)
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:350
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:207
virtual ~DecoderThread()
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:337
void addVideoListener(FFmpegVideoListener *listener)
add a listener to receive video frames for displaying and to get timestamp notifications.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:138
AVCodecContext * getAudioContext() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:743
int getVideoChannels() const
returns the number of audio channels in the video file.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:124
double getVideoPixelAspect() const
This will return the aspect ratio of each pixel.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:165
double getFramesPerSecond() const
Return the framerate.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:701
juce::File getVideoFileName() const
Returns the currently opened video file.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:97
int getNumChannels() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:731
int getVideoWidth() const
get the width of the video images according to decoder
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:148
juce::int64 getNextReadPosition() const override
Returns the sample count of the next sample to be returned by getNextAudioBlock.
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:267
void closeMovieFile()
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:91
double getSampleRate() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:715
void removeVideoListener(FFmpegVideoListener *listener)
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:415
enum AVPixelFormat getPixelFormat() const
get the pixel format of the video images according to decoder, will be converted to BGR0 to be displa...
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:677
enum AVSampleFormat getSampleFormat() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:670
double getDuration() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:723
double getLastVideoPTS() const
Definition: filmstro_ffmpeg_FFmpegVideoReader.cpp:133