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