You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
Completely rewrote audio encoding API (old one was depreciated)
Integrated new debug output, which makes troubleshooting issues much easier Simplified the Writer API calls (some methods now get automatically called if needed). Now a few simple methods can write an entire video file.
This commit is contained in:
@@ -73,7 +73,8 @@ namespace openshot
|
||||
* to generate openshot::Frame objects needed for writing. Be sure to use valid bit rates, frame
|
||||
* rates, and sample rates (each format / codec has a limited # of valid options).
|
||||
*
|
||||
* @code
|
||||
* @code SIMPLE EXAMPLE
|
||||
*
|
||||
* // Create a reader for a video
|
||||
* FFmpegReader r("MyAwesomeVideo.webm");
|
||||
* r.Open(); // Open the reader
|
||||
@@ -85,16 +86,54 @@ namespace openshot
|
||||
* w.SetAudioOptions(true, "libvorbis", 44100, 2, 128000); // Sample Rate: 44100, Channels: 2, Bitrate: 128000
|
||||
* 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
|
||||
*
|
||||
* // Prepare Streams
|
||||
* w.PrepareStreams();
|
||||
*
|
||||
* // Write header
|
||||
* w.WriteHeader();
|
||||
* // Open the writer
|
||||
* w.Open();
|
||||
*
|
||||
* // Write all frames from the reader
|
||||
* w.WriteFrame(&r, 1, r.info.video_length);
|
||||
*
|
||||
* // Write Footer
|
||||
* // Close the reader & writer
|
||||
* w.Close();
|
||||
* r.Close();
|
||||
* @endcode
|
||||
*
|
||||
* Here is a more advanced example, which sets some additional (and optional) encoding
|
||||
* options.
|
||||
*
|
||||
* @code ADVANCED WRITER EXAMPLE
|
||||
*
|
||||
* // Create a reader for a video
|
||||
* FFmpegReader r("MyAwesomeVideo.webm");
|
||||
* r.Open(); // Open the reader
|
||||
*
|
||||
* // Create a writer (which will create a WebM video)
|
||||
* FFmpegWriter w("/home/jonathan/NewVideo.webm");
|
||||
*
|
||||
* // Set options
|
||||
* w.SetAudioOptions(true, "libvorbis", 44100, 2, 128000); // Sample Rate: 44100, Channels: 2, Bitrate: 128000
|
||||
* 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
|
||||
*
|
||||
* // Prepare Streams (Optional method that must be called before any SetOption calls)
|
||||
* w.PrepareStreams();
|
||||
*
|
||||
* // Set some specific encoding options (Optional methods)
|
||||
* w.SetOption(VIDEO_STREAM, "qmin", "2" );
|
||||
* w.SetOption(VIDEO_STREAM, "qmax", "30" );
|
||||
* w.SetOption(VIDEO_STREAM, "crf", "10" );
|
||||
* w.SetOption(VIDEO_STREAM, "rc_min_rate", "2000000" );
|
||||
* w.SetOption(VIDEO_STREAM, "rc_max_rate", "4000000" );
|
||||
* w.SetOption(VIDEO_STREAM, "max_b_frames", "10" );
|
||||
*
|
||||
* // Write the header of the video file
|
||||
* w.WriteHeader();
|
||||
*
|
||||
* // Open the writer
|
||||
* w.Open();
|
||||
*
|
||||
* // Write all frames from the reader
|
||||
* w.WriteFrame(&r, 1, r.info.video_length);
|
||||
*
|
||||
* // Write the trailer of the video file
|
||||
* w.WriteTrailer();
|
||||
*
|
||||
* // Close the reader & writer
|
||||
@@ -108,9 +147,14 @@ namespace openshot
|
||||
string path;
|
||||
int cache_size;
|
||||
bool is_writing;
|
||||
bool is_open;
|
||||
int64 write_video_count;
|
||||
int64 write_audio_count;
|
||||
|
||||
bool prepare_streams;
|
||||
bool write_header;
|
||||
bool write_trailer;
|
||||
|
||||
AVOutputFormat *fmt;
|
||||
AVFormatContext *oc;
|
||||
AVStream *audio_st, *video_st;
|
||||
@@ -130,6 +174,8 @@ namespace openshot
|
||||
int initial_audio_input_frame_size;
|
||||
int audio_input_position;
|
||||
AudioResampler *resampler;
|
||||
AVAudioResampleContext *avr;
|
||||
AVAudioResampleContext *avr_planar;
|
||||
|
||||
/* Resample options */
|
||||
int original_sample_rate;
|
||||
@@ -174,6 +220,11 @@ namespace openshot
|
||||
/// initialize streams
|
||||
void initialize_streams();
|
||||
|
||||
/// @brief Init a collection of software rescalers (thread safe)
|
||||
/// @param source_width The source width of the image scalers (used to cache a bunch of scalers)
|
||||
/// @param source_height The source height of the image scalers (used to cache a bunch of scalers)
|
||||
void InitScalers(int source_width, int source_height);
|
||||
|
||||
/// open audio codec
|
||||
void open_audio(AVFormatContext *oc, AVStream *st);
|
||||
|
||||
@@ -194,7 +245,8 @@ namespace openshot
|
||||
|
||||
public:
|
||||
|
||||
/// Constructor for FFmpegWriter. Throws one of the following exceptions.
|
||||
/// @brief Constructor for FFmpegWriter. Throws one of the following exceptions.
|
||||
/// @param path The file path of the video file you want to open and read
|
||||
FFmpegWriter(string path) throw(InvalidFile, InvalidFormat, InvalidCodec, InvalidOptions, OutOfMemory);
|
||||
|
||||
/// Close the writer
|
||||
@@ -203,44 +255,76 @@ namespace openshot
|
||||
/// Get the cache size (number of frames to queue before writing)
|
||||
int GetCacheSize() { return cache_size; };
|
||||
|
||||
/// Init a collection of software rescalers (thread safe)
|
||||
void InitScalers(int source_width, int source_height);
|
||||
/// Determine if writer is open or closed
|
||||
bool IsOpen() { return is_open; };
|
||||
|
||||
/// Open writer
|
||||
void Open() throw(InvalidFile, InvalidCodec);
|
||||
|
||||
/// Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
|
||||
void OutputStreamInfo();
|
||||
|
||||
/// Prepare & initialize streams and open codecs
|
||||
/// @brief Prepare & initialize streams and open codecs. This method is called automatically
|
||||
/// by the Open() method if this method has not yet been called.
|
||||
void PrepareStreams();
|
||||
|
||||
/// Remove & deallocate all software scalers
|
||||
void RemoveScalers();
|
||||
|
||||
/// Set audio resample options
|
||||
/// @brief Set audio resample options
|
||||
/// @param sample_rate The number of samples per second of the audio
|
||||
/// @param channels The number of audio channels
|
||||
void ResampleAudio(int sample_rate, int channels);
|
||||
|
||||
/// Set audio export options
|
||||
void SetAudioOptions(bool has_audio, string codec, int sample_rate, int channels, int bit_rate);
|
||||
/// @brief Set audio export options
|
||||
/// @param has_audio Does this file need an audio stream?
|
||||
/// @param codec The codec used to encode the audio for this file
|
||||
/// @param sample_rate The number of audio samples needed in this file
|
||||
/// @param channels The number of audio channels needed in this file
|
||||
/// @param channel_layout The 'layout' of audio channels (i.e. mono, stereo, surround, etc...)
|
||||
/// @param bit_rate The audio bit rate used during encoding
|
||||
void SetAudioOptions(bool has_audio, string codec, int sample_rate, int channels, ChannelLayout channel_layout, int bit_rate);
|
||||
|
||||
/// Set the cache size (number of frames to queue before writing)
|
||||
/// @brief Set the cache size
|
||||
/// @param new_size The number of frames to queue before writing to the file
|
||||
void SetCacheSize(int new_size) { cache_size = new_size; };
|
||||
|
||||
/// Set video export options
|
||||
/// @brief Set video export options
|
||||
/// @param has_video Does this file need a video stream
|
||||
/// @param codec The codec used to encode the images in this video
|
||||
/// @param fps The number of frames per second
|
||||
/// @param width The width in pixels of this video
|
||||
/// @param height The height in pixels of this video
|
||||
/// @param pixel_ratio The shape of the pixels represented as a openshot::Fraction (1x1 is most common / square pixels)
|
||||
/// @param interlaced Does this video need to be interlaced?
|
||||
/// @param top_field_first Which frame should be used as the top field?
|
||||
/// @param bit_rate The video bit rate used during encoding
|
||||
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);
|
||||
|
||||
/// Set custom options (some codecs accept additional params)
|
||||
void SetOption(StreamType stream, string name, string value);
|
||||
/// @brief Set custom options (some codecs accept additional params). This must be called after the
|
||||
/// PrepareStreams() method, otherwise the streams have not been initialized yet.
|
||||
/// @param stream The stream (openshot::StreamType) this option should apply to
|
||||
/// @param name The name of the option you want to set (i.e. qmin, qmax, etc...)
|
||||
/// @param value The new value of this option
|
||||
void SetOption(StreamType stream, string name, string value) throw(NoStreamsFound, InvalidOptions);
|
||||
|
||||
/// Write the file header (after the options are set)
|
||||
/// @brief Write the file header (after the options are set). This method is called automatically
|
||||
/// by the Open() method if this method has not yet been called.
|
||||
void WriteHeader();
|
||||
|
||||
/// Add a frame to the stack waiting to be encoded.
|
||||
void WriteFrame(tr1::shared_ptr<Frame> frame);
|
||||
/// @brief Add a frame to the stack waiting to be encoded.
|
||||
/// @param frame The openshot::Frame object to write to this image
|
||||
void WriteFrame(tr1::shared_ptr<Frame> frame) throw(WriterClosed);
|
||||
|
||||
/// Write a block of frames from a reader
|
||||
void WriteFrame(ReaderBase* reader, int start, int length);
|
||||
/// @brief Write a block of frames from a reader
|
||||
/// @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);
|
||||
|
||||
/// Write the file trailer (after all frames are written)
|
||||
/// @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.
|
||||
void WriteTrailer();
|
||||
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
84
src/Main.cpp
84
src/Main.cpp
@@ -43,6 +43,81 @@ using namespace tr1;
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
// Reader
|
||||
FFmpegReader r9("/home/jonathan/Videos/sintel-1024-surround.mp4");
|
||||
r9.Open();
|
||||
//r9.info.has_audio = false;
|
||||
//r9.enable_seek = false;
|
||||
//r9.debug = true;
|
||||
|
||||
/* WRITER ---------------- */
|
||||
//FFmpegWriter w9("/home/jonathan/output.webm");
|
||||
//w9.debug = true;
|
||||
ImageWriter w9("/home/jonathan/output.gif");
|
||||
|
||||
// Set options
|
||||
//w9.SetAudioOptions(true, "libvorbis", 48000, r9.info.channels, r9.info.channel_layout, 120000);
|
||||
//w9.SetVideoOptions(true, "libvpx", r9.info.fps, r9.info.width, r9.info.height, r9.info.pixel_ratio, false, false, 1500000);
|
||||
//w9.SetVideoOptions(true, "rawvideo", r9.info.fps, 400, 2, r9.info.pixel_ratio, false, false, 20000000);
|
||||
w9.SetVideoOptions("GIF", r9.info.fps, r9.info.width, r9.info.height, 70, 1, true);
|
||||
|
||||
// Open writer
|
||||
w9.Open();
|
||||
|
||||
// Prepare Streams
|
||||
//w9.PrepareStreams();
|
||||
|
||||
// w9.SetOption(VIDEO_STREAM, "qmin", "2" );
|
||||
// w9.SetOption(VIDEO_STREAM, "qmax", "30" );
|
||||
// w9.SetOption(VIDEO_STREAM, "crf", "10" );
|
||||
// w9.SetOption(VIDEO_STREAM, "rc_min_rate", "2000000" );
|
||||
// w9.SetOption(VIDEO_STREAM, "rc_max_rate", "4000000" );
|
||||
// w9.SetOption(VIDEO_STREAM, "max_b_frames", "10" );
|
||||
|
||||
// Write header
|
||||
//w9.WriteHeader();
|
||||
|
||||
//r9.DisplayInfo();
|
||||
|
||||
// 147000 frames, 28100 frames
|
||||
//for (int frame = 1; frame <= (r9.info.video_length - 1); frame++)
|
||||
for (int frame = 500; frame <= 530; frame++)
|
||||
//int frame = 1;
|
||||
//while (true)
|
||||
{
|
||||
//int frame_number = (rand() % 750) + 1;
|
||||
int frame_number = ( frame);
|
||||
|
||||
//cout << "queue " << frame << " (frame: " << frame_number << ") ";
|
||||
tr1::shared_ptr<Frame> f = r9.GetFrame(frame_number);
|
||||
//cout << "(" << f->number << ", " << f << ")" << endl;
|
||||
//f->DisplayWaveform();
|
||||
//f->AddColor(r9.info.width, r9.info.height, "blue");
|
||||
w9.WriteFrame(f);
|
||||
|
||||
//frame++;
|
||||
}
|
||||
|
||||
cout << "done looping" << endl;
|
||||
|
||||
// Write Footer
|
||||
//w9.WriteTrailer();
|
||||
|
||||
// Close writer & reader
|
||||
w9.Close();
|
||||
|
||||
// Close timeline
|
||||
r9.Close();
|
||||
/* ---------------- */
|
||||
cout << "happy ending" << endl;
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FFmpegReader sinelReader("/home/jonathan/Videos/sintel_trailer-720p.mp4");
|
||||
//sinelReader.debug = true;
|
||||
sinelReader.Open();
|
||||
@@ -59,15 +134,16 @@ int main(int argc, char* argv[])
|
||||
tr1::shared_ptr<Frame> f = sinelReader.GetFrame(frame_number);
|
||||
//f->AddOverlayNumber(frame_number);
|
||||
//f->Display();
|
||||
f->DisplayWaveform();
|
||||
|
||||
//if (x == 7654)
|
||||
sinelReader.debug = true;
|
||||
//f->DisplayWaveform();
|
||||
// sinelReader.debug = true;
|
||||
|
||||
//if (x == 7655)
|
||||
// break;
|
||||
}
|
||||
|
||||
cout << sinelReader.OutputDebugJSON() << endl;
|
||||
//cout << sinelReader.OutputDebugJSON() << endl;
|
||||
sinelReader.Close();
|
||||
return 0;
|
||||
|
||||
@@ -175,7 +251,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Set options
|
||||
//w.SetAudioOptions(true, "libvorbis", 48000, 2, 188000);
|
||||
w.SetAudioOptions(true, "libmp3lame", 44100, 1, 12800);
|
||||
w.SetAudioOptions(true, "libmp3lame", 44100, 1, LAYOUT_STEREO, 12800);
|
||||
w.SetVideoOptions(true, "mpeg4", Fraction(24,1), 1280, 720, Fraction(1,1), false, false, 30000000);
|
||||
//w.SetVideoOptions(true, "libmp3lame", openshot::Fraction(30,1), 720, 360, Fraction(1,1), false, false, 3000000);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user