OpenShot Library | libopenshot  0.2.5
FFmpegWriter.h
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Header file for FFmpegWriter class
4  * @author Jonathan Thomas <jonathan@openshot.org>, Fabrice Bellard
5  *
6  * @ref License
7  */
8 
9 /* LICENSE
10  *
11  * Copyright (c) 2008-2019 OpenShot Studios, LLC, Fabrice Bellard
12  * (http://www.openshotstudios.com). This file is part of
13  * OpenShot Library (http://www.openshot.org), an open-source project
14  * dedicated to delivering high quality video editing and animation solutions
15  * to the world.
16  *
17  * This file is originally based on the Libavformat API example, and then modified
18  * by the libopenshot project.
19  *
20  * OpenShot Library is free software: you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License as published by
22  * the Free Software Foundation, either version 3 of the License, or
23  * (at your option) any later version.
24  * * OpenShot Library (libopenshot) is free software: you can redistribute it
25  * and/or modify it under the terms of the GNU Lesser General Public License
26  * as published by the Free Software Foundation, either version 3 of the
27  * License, or (at your option) any later version.
28  *
29  * OpenShot Library (libopenshot) is distributed in the hope that it will be
30  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32  * GNU Lesser General Public License for more details.
33  *
34  * You should have received a copy of the GNU Lesser General Public License
35  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
36  */
37 
38 
39 #ifndef OPENSHOT_FFMPEG_WRITER_H
40 #define OPENSHOT_FFMPEG_WRITER_H
41 
42 #include "ReaderBase.h"
43 #include "WriterBase.h"
44 
45 // Include FFmpeg headers and macros
46 #include "FFmpegUtilities.h"
47 
48 #include <cmath>
49 #include <ctime>
50 #include <iostream>
51 #include <stdio.h>
52 #include <unistd.h>
53 #include "CacheMemory.h"
54 #include "Exceptions.h"
55 #include "OpenMPUtilities.h"
56 #include "ZmqLogger.h"
57 #include "Settings.h"
58 
59 
60 namespace openshot {
61 
62  /// This enumeration designates the type of stream when encoding (video or audio)
63  enum StreamType {
64  VIDEO_STREAM, ///< A video stream (used to determine which type of stream)
65  AUDIO_STREAM ///< An audio stream (used to determine which type of stream)
66  };
67 
68  /**
69  * @brief This class uses the FFmpeg libraries, to write and encode video files and audio files.
70  *
71  * All FFmpeg options can be set using the SetOption() method, and any Reader may be used
72  * to generate openshot::Frame objects needed for writing. Be sure to use valid bit rates, frame
73  * rates, and sample rates (each format / codec has a limited # of valid options).
74  *
75  * @code SIMPLE EXAMPLE
76  *
77  * // Create a reader for a video
78  * openshot::FFmpegReader r("MyAwesomeVideo.webm");
79  * r.Open(); // Open the target reader
80  *
81  * // Create a writer (which will create a WebM video)
82  * openshot::FFmpegWriter w("/home/jonathan/NewVideo.webm");
83  *
84  * // Set options
85  *
86  * // Sample Rate: 44100, Channels: 2, Bitrate: 128000
87  * w.SetAudioOptions(true, "libvorbis", 44100, 2, openshot::ChannelLayout::LAYOUT_STEREO, 128000);
88  *
89  * // FPS: 24, Size: 720x480, Pixel Ratio: 1/1, Bitrate: 300000
90  * w.SetVideoOptions(true, "libvpx", openshot::Fraction(24,1), 720, 480, openshot::Fraction(1,1), false, false, 300000);
91  *
92  * // Open the writer
93  * w.Open();
94  *
95  * // Write all frames from the reader
96  * w.WriteFrame(&r, 1, r.info.video_length);
97  *
98  * // Close the reader & writer
99  * w.Close();
100  * r.Close();
101  * @endcode
102  *
103  * Here is a more advanced example, which sets some additional (and optional) encoding
104  * options.
105  *
106  * @code ADVANCED WRITER EXAMPLE
107  *
108  * // Create a reader for a video
109  * openshot::FFmpegReader r("MyAwesomeVideo.webm");
110  * r.Open(); // Open the reader
111  *
112  * // Create a writer (which will create a WebM video)
113  * openshot::FFmpegWriter w("/home/jonathan/NewVideo.webm");
114  *
115  * // Set options
116  *
117  * // Sample Rate: 44100, Channels: 2, Bitrate: 128000
118  * w.SetAudioOptions(true, "libvorbis", 44100, 2, openshot::ChannelLayout::LAYOUT_STEREO, 128000);
119  *
120  * // FPS: 24, Size: 720x480, Pixel Ratio: 1/1, Bitrate: 300000
121  * w.SetVideoOptions(true, "libvpx", openshot::Fraction(24,1), 720, 480, openshot::Fraction(1,1), false, false, 300000);
122  *
123  * // Prepare Streams (Optional method that must be called before any SetOption calls)
124  * w.PrepareStreams();
125  *
126  * // Set some specific encoding options (Optional methods)
127  * w.SetOption(VIDEO_STREAM, "qmin", "2" );
128  * w.SetOption(VIDEO_STREAM, "qmax", "30" );
129  * w.SetOption(VIDEO_STREAM, "crf", "10" );
130  * w.SetOption(VIDEO_STREAM, "rc_min_rate", "2000000" );
131  * w.SetOption(VIDEO_STREAM, "rc_max_rate", "4000000" );
132  * w.SetOption(VIDEO_STREAM, "max_b_frames", "10" );
133  *
134  * // Write the header of the video file
135  * w.WriteHeader();
136  *
137  * // Open the writer
138  * w.Open();
139  *
140  * // Write all frames from the reader
141  * w.WriteFrame(&r, 1, r.info.video_length);
142  *
143  * // Write the trailer of the video file
144  * w.WriteTrailer();
145  *
146  * // Close the reader & writer
147  * w.Close();
148  * r.Close();
149  * @endcode
150  */
151  class FFmpegWriter : public WriterBase {
152  private:
153  std::string path;
154  int cache_size;
155  bool is_writing;
156  bool is_open;
157  int64_t write_video_count;
158  int64_t write_audio_count;
159 
160  bool prepare_streams;
161  bool write_header;
162  bool write_trailer;
163 
164  AVOutputFormat *fmt;
165  AVFormatContext *oc;
166  AVStream *audio_st, *video_st;
167  AVCodecContext *video_codec;
168  AVCodecContext *audio_codec;
169  SwsContext *img_convert_ctx;
170  double audio_pts, video_pts;
171  int16_t *samples;
172  uint8_t *audio_outbuf;
173  uint8_t *audio_encoder_buffer;
174 
175  int num_of_rescalers;
176  int rescaler_position;
177  std::vector<SwsContext *> image_rescalers;
178 
179  int audio_outbuf_size;
180  int audio_input_frame_size;
181  int initial_audio_input_frame_size;
182  int audio_input_position;
183  int audio_encoder_buffer_size;
184  SWRCONTEXT *avr;
185  SWRCONTEXT *avr_planar;
186 
187  /* Resample options */
188  int original_sample_rate;
189  int original_channels;
190 
191  std::shared_ptr<openshot::Frame> last_frame;
192  std::deque<std::shared_ptr<openshot::Frame> > spooled_audio_frames;
193  std::deque<std::shared_ptr<openshot::Frame> > spooled_video_frames;
194 
195  std::deque<std::shared_ptr<openshot::Frame> > queued_audio_frames;
196  std::deque<std::shared_ptr<openshot::Frame> > queued_video_frames;
197 
198  std::deque<std::shared_ptr<openshot::Frame> > processed_frames;
199  std::deque<std::shared_ptr<openshot::Frame> > deallocate_frames;
200 
201  std::map<std::shared_ptr<openshot::Frame>, AVFrame *> av_frames;
202 
203  /// Add an AVFrame to the cache
204  void add_avframe(std::shared_ptr<openshot::Frame> frame, AVFrame *av_frame);
205 
206  /// Add an audio output stream
207  AVStream *add_audio_stream();
208 
209  /// Add a video output stream
210  AVStream *add_video_stream();
211 
212  /// Allocate an AVFrame object
213  AVFrame *allocate_avframe(PixelFormat pix_fmt, int width, int height, int *buffer_size, uint8_t *new_buffer);
214 
215  /// Auto detect format (from path)
216  void auto_detect_format();
217 
218  /// Close the audio codec
219  void close_audio(AVFormatContext *oc, AVStream *st);
220 
221  /// Close the video codec
222  void close_video(AVFormatContext *oc, AVStream *st);
223 
224  /// Flush encoders
225  void flush_encoders();
226 
227  /// initialize streams
228  void initialize_streams();
229 
230  /// @brief Init a collection of software rescalers (thread safe)
231  /// @param source_width The source width of the image scalers (used to cache a bunch of scalers)
232  /// @param source_height The source height of the image scalers (used to cache a bunch of scalers)
233  void InitScalers(int source_width, int source_height);
234 
235  /// open audio codec
236  void open_audio(AVFormatContext *oc, AVStream *st);
237 
238  /// open video codec
239  void open_video(AVFormatContext *oc, AVStream *st);
240 
241  /// process video frame
242  void process_video_packet(std::shared_ptr<openshot::Frame> frame);
243 
244  /// write all queued frames' audio to the video file
245  void write_audio_packets(bool is_final);
246 
247  /// write video frame
248  bool write_video_packet(std::shared_ptr<openshot::Frame> frame, AVFrame *frame_final);
249 
250  /// write all queued frames
251  void write_queued_frames();
252 
253  public:
254 
255  /// @brief Constructor for FFmpegWriter. Throws one of the following exceptions.
256  /// @param path The file path of the video file you want to open and read
257  FFmpegWriter(std::string path);
258 
259  /// Close the writer
260  void Close();
261 
262  /// Get the cache size (number of frames to queue before writing)
263  int GetCacheSize() { return cache_size; };
264 
265  /// Determine if writer is open or closed
266  bool IsOpen() { return is_open; };
267 
268  /// Determine if codec name is valid
269  static bool IsValidCodec(std::string codec_name);
270 
271  /// Open writer
272  void Open();
273 
274  /// Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
275  void OutputStreamInfo();
276 
277  /// @brief Prepare & initialize streams and open codecs. This method is called automatically
278  /// by the Open() method if this method has not yet been called.
279  void PrepareStreams();
280 
281  /// Remove & deallocate all software scalers
282  void RemoveScalers();
283 
284  /// @brief Set audio resample options
285  /// @param sample_rate The number of samples per second of the audio
286  /// @param channels The number of audio channels
287  void ResampleAudio(int sample_rate, int channels);
288 
289  /// @brief Set audio export options
290  /// @param has_audio Does this file need an audio stream?
291  /// @param codec The codec used to encode the audio for this file
292  /// @param sample_rate The number of audio samples needed in this file
293  /// @param channels The number of audio channels needed in this file
294  /// @param channel_layout The 'layout' of audio channels (i.e. mono, stereo, surround, etc...)
295  /// @param bit_rate The audio bit rate used during encoding
296  ///
297  /// \note This is an overloaded function.
298  void SetAudioOptions(bool has_audio, std::string codec, int sample_rate, int channels, openshot::ChannelLayout channel_layout, int bit_rate);
299 
300  /// @brief Set audio export options.
301  ///
302  /// Enables the stream and configures a default 2-channel stereo layout.
303  ///
304  /// @param codec The codec used to encode the audio for this file
305  /// @param sample_rate The number of audio samples needed in this file
306  /// @param bit_rate The audio bit rate used during encoding
307  ///
308  /// \note This is an overloaded function.
309  void SetAudioOptions(std::string codec, int sample_rate, int bit_rate);
310 
311  /// @brief Set the cache size
312  /// @param new_size The number of frames to queue before writing to the file
313  void SetCacheSize(int new_size) { cache_size = new_size; };
314 
315  /// @brief Set video export options
316  /// @param has_video Does this file need a video stream
317  /// @param codec The codec used to encode the images in this video
318  /// @param fps The number of frames per second
319  /// @param width The width in pixels of this video
320  /// @param height The height in pixels of this video
321  /// @param pixel_ratio The shape of the pixels represented as a openshot::Fraction (1x1 is most common / square pixels)
322  /// @param interlaced Does this video need to be interlaced?
323  /// @param top_field_first Which frame should be used as the top field?
324  /// @param bit_rate The video bit rate used during encoding
325  ///
326  /// \note This is an overloaded function.
327  void SetVideoOptions(bool has_video, std::string codec, openshot::Fraction fps, int width, int height, openshot::Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate);
328 
329  /// @brief Set video export options.
330  ///
331  /// Enables the stream and configures non-interlaced video with a 1:1 pixel aspect ratio.
332  ///
333  /// @param codec The codec used to encode the images in this video
334  /// @param width The width in pixels of this video
335  /// @param height The height in pixels of this video
336  /// @param fps The number of frames per second
337  /// @param bit_rate The video bit rate used during encoding
338  ///
339  /// \note This is an overloaded function.
340  /// \warning Observe the argument order, which is consistent with the openshot::Timeline constructor, but differs from the other signature.
341  void SetVideoOptions(std::string codec, int width, int height, openshot::Fraction fps, int bit_rate);
342 
343  /// @brief Set custom options (some codecs accept additional params). This must be called after the
344  /// PrepareStreams() method, otherwise the streams have not been initialized yet.
345  ///
346  /// @param stream The stream (openshot::StreamType) this option should apply to
347  /// @param name The name of the option you want to set (i.e. qmin, qmax, etc...)
348  /// @param value The new value of this option
349  void SetOption(openshot::StreamType stream, std::string name, std::string value);
350 
351  /// @brief Write the file header (after the options are set). This method is called automatically
352  /// by the Open() method if this method has not yet been called.
353  void WriteHeader();
354 
355  /// @brief Add a frame to the stack waiting to be encoded.
356  /// @param frame The openshot::Frame object to write to this image
357  ///
358  /// \note This is an overloaded function.
359  void WriteFrame(std::shared_ptr<openshot::Frame> frame);
360 
361  /// @brief Write a block of frames from a reader
362  /// @param reader A openshot::ReaderBase object which will provide frames to be written
363  /// @param start The starting frame number of the reader
364  /// @param length The number of frames to write
365  ///
366  /// \note This is an overloaded function.
367  void WriteFrame(openshot::ReaderBase *reader, int64_t start, int64_t length);
368 
369  /// @brief Write the file trailer (after all frames are written). This is called automatically
370  /// by the Close() method if this method has not yet been called.
371  void WriteTrailer();
372 
373  };
374 
375 }
376 
377 #endif
Settings.h
Header file for global Settings class.
openshot::AUDIO_STREAM
@ AUDIO_STREAM
An audio stream (used to determine which type of stream)
Definition: FFmpegWriter.h:65
FFmpegUtilities.h
Header file for FFmpegUtilities.
WriterBase.h
Header file for WriterBase class.
openshot::FFmpegWriter::ResampleAudio
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
Definition: FFmpegWriter.cpp:2165
openshot::FFmpegWriter::OutputStreamInfo
void OutputStreamInfo()
Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
Definition: FFmpegWriter.cpp:2134
PixelFormat
#define PixelFormat
Definition: FFmpegUtilities.h:111
openshot
This namespace is the default namespace for all code in the openshot library.
Definition: AudioBufferSource.h:39
openshot::FFmpegWriter::FFmpegWriter
FFmpegWriter(std::string path)
Constructor for FFmpegWriter. Throws one of the following exceptions.
Definition: FFmpegWriter.cpp:86
openshot::Fraction
This class represents a fraction.
Definition: Fraction.h:45
openshot::FFmpegWriter::Open
void Open()
Open writer.
Definition: FFmpegWriter.cpp:106
openshot::FFmpegWriter::SetVideoOptions
void SetVideoOptions(bool has_video, std::string codec, openshot::Fraction fps, int width, int height, openshot::Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate)
Set video export options.
Definition: FFmpegWriter.cpp:169
openshot::FFmpegWriter
This class uses the FFmpeg libraries, to write and encode video files and audio files.
Definition: FFmpegWriter.h:151
openshot::FFmpegWriter::IsOpen
bool IsOpen()
Determine if writer is open or closed.
Definition: FFmpegWriter.h:266
ZmqLogger.h
Header file for ZeroMQ-based Logger class.
openshot::FFmpegWriter::SetOption
void SetOption(openshot::StreamType stream, std::string name, std::string value)
Set custom options (some codecs accept additional params). This must be called after the PrepareStrea...
Definition: FFmpegWriter.cpp:333
openshot::FFmpegWriter::GetCacheSize
int GetCacheSize()
Get the cache size (number of frames to queue before writing)
Definition: FFmpegWriter.h:263
CacheMemory.h
Header file for CacheMemory class.
SWRCONTEXT
#define SWRCONTEXT
Definition: FFmpegUtilities.h:148
openshot::VIDEO_STREAM
@ VIDEO_STREAM
A video stream (used to determine which type of stream)
Definition: FFmpegWriter.h:64
openshot::FFmpegWriter::WriteFrame
void WriteFrame(std::shared_ptr< openshot::Frame > frame)
Add a frame to the stack waiting to be encoded.
Definition: FFmpegWriter.cpp:619
ReaderBase.h
Header file for ReaderBase class.
openshot::FFmpegWriter::Close
void Close()
Close the writer.
Definition: FFmpegWriter.cpp:1011
openshot::FFmpegWriter::SetCacheSize
void SetCacheSize(int new_size)
Set the cache size.
Definition: FFmpegWriter.h:313
openshot::FFmpegWriter::IsValidCodec
static bool IsValidCodec(std::string codec_name)
Determine if codec name is valid.
Definition: FFmpegWriter.cpp:549
OpenMPUtilities.h
Header file for OpenMPUtilities (set some common macros)
openshot::FFmpegWriter::WriteTrailer
void WriteTrailer()
Write the file trailer (after all frames are written). This is called automatically by the Close() me...
Definition: FFmpegWriter.cpp:774
openshot::ReaderBase
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:98
openshot::ChannelLayout
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround,...
Definition: ChannelLayouts.h:47
openshot::FFmpegWriter::SetAudioOptions
void SetAudioOptions(bool has_audio, std::string codec, int sample_rate, int channels, openshot::ChannelLayout channel_layout, int bit_rate)
Set audio export options.
Definition: FFmpegWriter.cpp:289
openshot::StreamType
StreamType
This enumeration designates the type of stream when encoding (video or audio)
Definition: FFmpegWriter.h:63
openshot::FFmpegWriter::PrepareStreams
void PrepareStreams()
Prepare & initialize streams and open codecs. This method is called automatically by the Open() metho...
Definition: FFmpegWriter.cpp:561
openshot::FFmpegWriter::RemoveScalers
void RemoveScalers()
Remove & deallocate all software scalers.
Definition: FFmpegWriter.cpp:2171
Exceptions.h
Header file for all Exception classes.
openshot::FFmpegWriter::WriteHeader
void WriteHeader()
Write the file header (after the options are set). This method is called automatically by the Open() ...
Definition: FFmpegWriter.cpp:575
openshot::WriterBase
This abstract class is the base class, used by writers. Writers are types of classes that encode vide...
Definition: WriterBase.h:88