You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
Replaced avcodec_encode_audio with avcodec_encode_audio2, and completely redid the way PTS values are calculated and set. Another nice improvement!
This commit is contained in:
@@ -31,7 +31,7 @@ FFmpegWriter::FFmpegWriter(string path) throw (InvalidFile, InvalidFormat, Inval
|
||||
path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), audio_pts(0), video_pts(0), samples(NULL),
|
||||
audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0),
|
||||
initial_audio_input_frame_size(0), resampler(NULL), img_convert_ctx(NULL), cache_size(8), num_of_rescalers(32),
|
||||
rescaler_position(0), video_codec(NULL), audio_codec(NULL), is_writing(false), write_video_count(0), write_audio_count(0)
|
||||
rescaler_position(0), video_codec(NULL), audio_codec(NULL), is_writing(false), write_video_count(1), write_audio_count(1)
|
||||
{
|
||||
|
||||
// Init FileInfo struct (clear all values)
|
||||
@@ -440,16 +440,17 @@ void FFmpegWriter::WriteTrailer()
|
||||
// ignore the final frames.
|
||||
if (last_frame)
|
||||
{
|
||||
// Flush remaining packets
|
||||
//av_write_frame(oc, NULL);
|
||||
av_interleaved_write_frame(oc, NULL);
|
||||
|
||||
// Create black frame
|
||||
tr1::shared_ptr<Frame> padding_frame(new Frame(999999, last_frame->GetWidth(), last_frame->GetHeight(), "#000000", last_frame->GetAudioSamplesCount(), last_frame->GetAudioChannelsCount()));
|
||||
padding_frame->AddColor(last_frame->GetWidth(), last_frame->GetHeight(), "#000000");
|
||||
//tr1::shared_ptr<Frame> padding_frame(new Frame(999999, last_frame->GetWidth(), last_frame->GetHeight(), "#000000", last_frame->GetAudioSamplesCount(), last_frame->GetAudioChannelsCount()));
|
||||
//padding_frame->AddColor(last_frame->GetWidth(), last_frame->GetHeight(), "#000000");
|
||||
|
||||
// Add the black frame many times
|
||||
//for (int p = 0; p < 25; p++)
|
||||
// WriteFrame(padding_frame);
|
||||
|
||||
// Flush remaining packets
|
||||
av_write_frame(oc, NULL);
|
||||
}
|
||||
|
||||
// Write any remaining queued frames to video file
|
||||
@@ -506,8 +507,8 @@ void FFmpegWriter::Close()
|
||||
}
|
||||
|
||||
// Reset frame counters
|
||||
write_video_count = 0;
|
||||
write_audio_count = 0;
|
||||
write_video_count = 1;
|
||||
write_audio_count = 1;
|
||||
|
||||
// Free the stream
|
||||
av_free(oc);
|
||||
@@ -546,6 +547,9 @@ AVStream* FFmpegWriter::add_audio_stream()
|
||||
if (!st)
|
||||
throw OutOfMemory("Could not allocate memory for the audio stream.", path);
|
||||
|
||||
// Set default values
|
||||
avcodec_get_context_defaults3(st->codec, codec);
|
||||
|
||||
c = st->codec;
|
||||
c->codec_id = codec->id;
|
||||
c->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
@@ -555,11 +559,11 @@ AVStream* FFmpegWriter::add_audio_stream()
|
||||
c->channels = info.channels;
|
||||
|
||||
// Check for valid timebase
|
||||
if (c->time_base.den == 0 || c->time_base.num == 0)
|
||||
{
|
||||
c->time_base.num = st->time_base.num;
|
||||
c->time_base.den = st->time_base.den;
|
||||
}
|
||||
// if (c->time_base.den == 0 || c->time_base.num == 0)
|
||||
// {
|
||||
// c->time_base.num = st->time_base.num;
|
||||
// c->time_base.den = st->time_base.den;
|
||||
// }
|
||||
|
||||
// Set valid sample rate (or throw error)
|
||||
if (codec->supported_samplerates) {
|
||||
@@ -632,6 +636,9 @@ AVStream* FFmpegWriter::add_video_stream()
|
||||
if (!st)
|
||||
throw OutOfMemory("Could not allocate memory for the video stream.", path);
|
||||
|
||||
// Set default values
|
||||
avcodec_get_context_defaults3(st->codec, codec);
|
||||
|
||||
c = st->codec;
|
||||
c->codec_id = codec->id;
|
||||
c->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
@@ -773,7 +780,6 @@ void FFmpegWriter::write_audio_packets()
|
||||
channels_in_frame = frame->GetAudioChannelsCount();
|
||||
|
||||
// Get audio sample array
|
||||
//float* frame_samples_float = new float(total_frame_samples);
|
||||
float* frame_samples_float = frame->GetInterleavedAudioSamples(info.sample_rate, new_sampler, &samples_in_frame);
|
||||
|
||||
// Calculate total samples
|
||||
@@ -799,7 +805,7 @@ void FFmpegWriter::write_audio_packets()
|
||||
int samples_position = 0;
|
||||
|
||||
|
||||
// Re-sample audio samples (into additinal channels or changing the sample format / number format)
|
||||
// Re-sample audio samples (into additional channels or changing the sample format / number format)
|
||||
// The sample rate has already been resampled using the GetInterleavedAudioSamples method.
|
||||
if (audio_codec->sample_fmt != AV_SAMPLE_FMT_S16 || info.channels != channels_in_frame) {
|
||||
|
||||
@@ -857,33 +863,66 @@ void FFmpegWriter::write_audio_packets()
|
||||
// Not enough samples to encode... so wait until the next frame
|
||||
break;
|
||||
|
||||
|
||||
// Increment PTS (in samples and scaled to the codec's timebase)
|
||||
write_audio_count += av_rescale_q(audio_codec->frame_size, AVRational{1, info.sample_rate}, audio_codec->time_base);
|
||||
|
||||
// Create AVFrame (and fill it with samples)
|
||||
AVFrame *frame_final = avcodec_alloc_frame();
|
||||
frame_final->nb_samples = audio_codec->frame_size;
|
||||
frame_final->pts = write_audio_count; // Set the AVFrame's PTS
|
||||
avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) samples,
|
||||
audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt) * audio_codec->channels, 0);
|
||||
|
||||
// Init the packet
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
pkt.data = NULL;
|
||||
pkt.size = 0;
|
||||
|
||||
// Increment counter, and set AVFrame PTS
|
||||
write_audio_count++;
|
||||
// Set the packet's PTS prior to encoding
|
||||
pkt.pts = pkt.dts = write_audio_count;
|
||||
|
||||
// Encode audio data
|
||||
pkt.size = avcodec_encode_audio(audio_codec, audio_outbuf, audio_outbuf_size, (short *) samples);
|
||||
/* encode the audio samples */
|
||||
int got_packet_ptr = 0;
|
||||
int error_code = avcodec_encode_audio2(audio_codec, &pkt, frame_final, &got_packet_ptr);
|
||||
|
||||
if (audio_codec->coded_frame && audio_codec->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
// Set the correct rescaled timestamp
|
||||
pkt.pts = av_rescale_q(audio_codec->coded_frame->pts, audio_codec->time_base, audio_st->time_base);
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
pkt.stream_index = audio_st->index;
|
||||
pkt.data = audio_outbuf;
|
||||
/* if zero size, it means the image was buffered */
|
||||
if (error_code == 0 && got_packet_ptr) {
|
||||
|
||||
/* write the compressed frame in the media file */
|
||||
int averror = 0;
|
||||
averror = av_interleaved_write_frame(oc, &pkt);
|
||||
if (averror != 0)
|
||||
{
|
||||
string error_description = av_err2str(averror);
|
||||
cout << "error: " << averror << ": " << error_description << endl;
|
||||
throw ErrorEncodingAudio("Error while writing audio frame", -1);
|
||||
// Since the PTS can change during encoding, set the value again. This seems like a huge hack,
|
||||
// but it fixes lots of PTS related issues when I do this.
|
||||
pkt.pts = pkt.dts = write_audio_count;
|
||||
|
||||
// Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
|
||||
if (pkt.pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(pkt.pts, audio_codec->time_base, audio_st->time_base);
|
||||
if (pkt.dts != AV_NOPTS_VALUE)
|
||||
pkt.dts = av_rescale_q(pkt.dts, audio_codec->time_base, audio_st->time_base);
|
||||
if (pkt.duration > 0)
|
||||
pkt.duration = av_rescale_q(pkt.duration, audio_codec->time_base, audio_st->time_base);
|
||||
|
||||
// set stream
|
||||
pkt.stream_index = audio_st->index;
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
|
||||
/* write the compressed frame in the media file */
|
||||
int averror = av_interleaved_write_frame(oc, &pkt);
|
||||
if (averror != 0)
|
||||
{
|
||||
string error_description = av_err2str(averror);
|
||||
cout << "error: " << averror << ": " << error_description << endl;
|
||||
throw ErrorEncodingAudio("Error while writing compressed audio frame", write_audio_count);
|
||||
}
|
||||
}
|
||||
|
||||
if (error_code < 0)
|
||||
cout << "Error encoding audio: " << error_code << endl;
|
||||
|
||||
// deallocate AVFrame
|
||||
//av_free(frame_final->data[0]);
|
||||
av_free(frame_final);
|
||||
|
||||
// deallocate memory for packet
|
||||
av_free_packet(&pkt);
|
||||
|
||||
@@ -1008,6 +1047,10 @@ void FFmpegWriter::write_video_packet(tr1::shared_ptr<Frame> frame, AVFrame* fra
|
||||
pkt.data= (uint8_t *)frame_final;
|
||||
pkt.size= sizeof(AVPicture);
|
||||
|
||||
// Increment PTS (1 per frame)
|
||||
write_video_count += 1;
|
||||
pkt.pts = write_video_count;
|
||||
|
||||
/* write the compressed frame in the media file */
|
||||
int averror = 0;
|
||||
averror = av_interleaved_write_frame(oc, &pkt);
|
||||
@@ -1026,9 +1069,10 @@ void FFmpegWriter::write_video_packet(tr1::shared_ptr<Frame> frame, AVFrame* fra
|
||||
av_init_packet(&pkt);
|
||||
pkt.data = NULL;
|
||||
pkt.size = 0;
|
||||
pkt.pts = pkt.dts = AV_NOPTS_VALUE;
|
||||
|
||||
// Increment video write counter
|
||||
write_video_count++;
|
||||
// Increment PTS (in frames and scaled to the codec's timebase)
|
||||
write_video_count += av_rescale_q(1, AVRational{info.fps.den, info.fps.num}, video_codec->time_base);
|
||||
|
||||
// Assign the initial AVFrame PTS from the frame counter
|
||||
frame_final->pts = write_video_count;
|
||||
@@ -1043,13 +1087,11 @@ void FFmpegWriter::write_video_packet(tr1::shared_ptr<Frame> frame, AVFrame* fra
|
||||
// set the timestamp
|
||||
if (pkt.pts != AV_NOPTS_VALUE)
|
||||
pkt.pts = av_rescale_q(pkt.pts, video_codec->time_base, video_st->time_base);
|
||||
//if (pkt.dts != AV_NOPTS_VALUE)
|
||||
// pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
|
||||
//pkt.pts = pkt.dts = AV_NOPTS_VALUE;
|
||||
|
||||
// pkt.stream_index = video_st->index;
|
||||
// pkt.pts = av_rescale_q(write_video_count, video_codec->time_base, video_st->time_base);
|
||||
// pkt.dts = AV_NOPTS_VALUE;
|
||||
if (pkt.dts != AV_NOPTS_VALUE)
|
||||
pkt.dts = av_rescale_q(pkt.dts, video_codec->time_base, video_st->time_base);
|
||||
if (pkt.duration > 0)
|
||||
pkt.duration = av_rescale_q(pkt.duration, video_codec->time_base, video_st->time_base);
|
||||
pkt.stream_index = video_st->index;
|
||||
|
||||
/* write the compressed frame in the media file */
|
||||
//int averror = av_write_frame(oc, &pkt);
|
||||
|
||||
@@ -243,7 +243,7 @@ void Frame::ClearWaveform()
|
||||
const Magick::PixelPacket* Frame::GetWaveformPixels(int width, int height)
|
||||
{
|
||||
// Get audio wave form image
|
||||
tr1::shared_ptr<Magick::Image> wave_image = GetWaveform(width, height);
|
||||
wave_image = GetWaveform(width, height);
|
||||
|
||||
// Return array of pixel packets
|
||||
return wave_image->getConstPixels(0,0, wave_image->columns(), wave_image->rows());
|
||||
|
||||
325
src/Main.cpp
325
src/Main.cpp
@@ -16,119 +16,101 @@ void FrameReady(int number)
|
||||
|
||||
int main()
|
||||
{
|
||||
// Keyframe time;
|
||||
// //time.AddPoint(1, 300);
|
||||
// time.AddPoint(1, 500, LINEAR);
|
||||
// time.AddPoint(400, 100);
|
||||
// time.AddPoint(500, 500);
|
||||
// time.PrintValues();
|
||||
// // Create timeline
|
||||
// Timeline t(640, 360, Framerate(24,1));
|
||||
//
|
||||
// return 0;
|
||||
|
||||
|
||||
// openshot::FFmpegReader r1("/home/jonathan/Videos/sintel-1024-stereo.mp4");
|
||||
// r1.Open();
|
||||
// FrameMapper map(&r1, Framerate(30,1), PULLDOWN_NONE);
|
||||
// map.PrintMapping();
|
||||
// // Add some clips
|
||||
// Clip c1(new FFmpegReader("/home/jonathan/Videos/sintel_trailer-720p.mp4"));
|
||||
// c1.Position(0.0);
|
||||
//
|
||||
// return 0;
|
||||
|
||||
|
||||
// Create timeline
|
||||
Timeline t(640, 360, Framerate(24,1));
|
||||
|
||||
// Add some clips
|
||||
Clip c1(new FFmpegReader("/home/jonathan/Videos/sintel_trailer-720p.mp4"));
|
||||
c1.Position(0.0);
|
||||
|
||||
// LINEAR Reverse
|
||||
//c1.time.AddPoint(1, 500, LINEAR);
|
||||
//c1.time.AddPoint(500, 1, LINEAR);
|
||||
|
||||
// LINEAR Slow Reverse (sounds wavy, due to periodic repeated frames)
|
||||
//c1.time.AddPoint(1, 500, LINEAR);
|
||||
//c1.time.AddPoint(500, 100, LINEAR);
|
||||
|
||||
// LINEAR Slow Reverse X2 (smooth)
|
||||
c1.time.AddPoint(1, 500, LINEAR);
|
||||
c1.time.AddPoint(500, 250, LINEAR);
|
||||
|
||||
// LINEAR Fast Reverse (sounds wavy, due to periodic repeated frames)
|
||||
//c1.time.AddPoint(1, 600, LINEAR);
|
||||
//c1.time.AddPoint(500, 1, LINEAR);
|
||||
|
||||
// LINEAR Slow Forward
|
||||
//c1.time.AddPoint(1, 1000, LINEAR);
|
||||
//c1.time.AddPoint(500, 1, LINEAR);
|
||||
|
||||
// // BEZIER Reverse
|
||||
// openshot::Point p1(1,500);
|
||||
// p1.handle_left = Coordinate(1,500);
|
||||
// p1.handle_right = Coordinate(250,500);
|
||||
// // LINEAR Reverse
|
||||
// //c1.time.AddPoint(1, 500, LINEAR);
|
||||
// //c1.time.AddPoint(500, 1, LINEAR);
|
||||
//
|
||||
// openshot::Point p2(500,100);
|
||||
// p1.handle_left = Coordinate(500,350);
|
||||
// p1.handle_right = Coordinate(500,100);
|
||||
// // LINEAR Slow Reverse (sounds wavy, due to periodic repeated frames)
|
||||
// //c1.time.AddPoint(1, 500, LINEAR);
|
||||
// //c1.time.AddPoint(500, 100, LINEAR);
|
||||
//
|
||||
// c1.time.AddPoint(p1);
|
||||
// c1.time.AddPoint(p2);
|
||||
|
||||
// // LINEAR Slow Reverse X2 (smooth)
|
||||
// c1.time.AddPoint(1, 500, LINEAR);
|
||||
// c1.time.AddPoint(500, 1, LINEAR);
|
||||
// c1.time.AddPoint(1, 500, LINEAR);
|
||||
// c1.time.AddPoint(200, 200);
|
||||
// c1.time.AddPoint(500, 500, LINEAR);
|
||||
c1.time.PrintValues();
|
||||
|
||||
// Add clips
|
||||
t.AddClip(&c1);
|
||||
|
||||
|
||||
// Create a writer
|
||||
FFmpegWriter w("/home/jonathan/output.webm");
|
||||
w.DisplayInfo();
|
||||
|
||||
// Set options
|
||||
//w.SetAudioOptions(true, "libmp3lame", 44100, 2, 128000, false);
|
||||
w.SetAudioOptions(true, "libvorbis", 44100, 2, 128000, false);
|
||||
w.SetVideoOptions(true, "libvpx", Fraction(24, 1), 640, 360, Fraction(1,1), false, false, 2000000);
|
||||
|
||||
// Prepare Streams
|
||||
w.PrepareStreams();
|
||||
|
||||
// Write header
|
||||
w.WriteHeader();
|
||||
|
||||
// Output stream info
|
||||
w.OutputStreamInfo();
|
||||
|
||||
for (int frame = 1; frame <= 500; frame++)
|
||||
{
|
||||
tr1::shared_ptr<Frame> f = t.GetFrame(frame);
|
||||
if (f)
|
||||
{
|
||||
//f->AddOverlayNumber(0);
|
||||
//if (frame >= 1 && frame <= 22)
|
||||
// f->DisplayWaveform();
|
||||
|
||||
// Write frame
|
||||
//cout << "queue frame " << frame << endl;
|
||||
cout << "queue frame " << frame << " (" << f->number << ", " << f << ")" << endl;
|
||||
w.WriteFrame(f);
|
||||
}
|
||||
}
|
||||
|
||||
// Write Footer
|
||||
w.WriteTrailer();
|
||||
|
||||
// Close writer & reader
|
||||
w.Close();
|
||||
|
||||
// Close timeline
|
||||
t.Close();
|
||||
|
||||
cout << "Successfully Finished Timeline DEMO" << endl;
|
||||
return 0;
|
||||
// c1.time.AddPoint(500, 250, LINEAR);
|
||||
//
|
||||
// // LINEAR Fast Reverse (sounds wavy, due to periodic repeated frames)
|
||||
// //c1.time.AddPoint(1, 600, LINEAR);
|
||||
// //c1.time.AddPoint(500, 1, LINEAR);
|
||||
//
|
||||
// // LINEAR Slow Forward
|
||||
// //c1.time.AddPoint(1, 1000, LINEAR);
|
||||
// //c1.time.AddPoint(500, 1, LINEAR);
|
||||
//
|
||||
//// // BEZIER Reverse
|
||||
//// openshot::Point p1(1,500);
|
||||
//// p1.handle_left = Coordinate(1,500);
|
||||
//// p1.handle_right = Coordinate(250,500);
|
||||
////
|
||||
//// openshot::Point p2(500,100);
|
||||
//// p1.handle_left = Coordinate(500,350);
|
||||
//// p1.handle_right = Coordinate(500,100);
|
||||
////
|
||||
//// c1.time.AddPoint(p1);
|
||||
//// c1.time.AddPoint(p2);
|
||||
//
|
||||
//// c1.time.AddPoint(1, 500, LINEAR);
|
||||
//// c1.time.AddPoint(500, 1, LINEAR);
|
||||
//// c1.time.AddPoint(1, 500, LINEAR);
|
||||
//// c1.time.AddPoint(200, 200);
|
||||
//// c1.time.AddPoint(500, 500, LINEAR);
|
||||
// c1.time.PrintValues();
|
||||
//
|
||||
// // Add clips
|
||||
// t.AddClip(&c1);
|
||||
//
|
||||
//
|
||||
// // Create a writer
|
||||
// FFmpegWriter w("/home/jonathan/output.webm");
|
||||
// w.DisplayInfo();
|
||||
//
|
||||
// // Set options
|
||||
// //w.SetAudioOptions(true, "libmp3lame", 44100, 2, 128000, false);
|
||||
// w.SetAudioOptions(true, "libvorbis", 44100, 2, 128000, false);
|
||||
// w.SetVideoOptions(true, "libvpx", Fraction(24, 1), 640, 360, Fraction(1,1), false, false, 2000000);
|
||||
//
|
||||
// // Prepare Streams
|
||||
// w.PrepareStreams();
|
||||
//
|
||||
// // Write header
|
||||
// w.WriteHeader();
|
||||
//
|
||||
// // Output stream info
|
||||
// w.OutputStreamInfo();
|
||||
//
|
||||
// for (int frame = 1; frame <= 500; frame++)
|
||||
// {
|
||||
// tr1::shared_ptr<Frame> f = t.GetFrame(frame);
|
||||
// if (f)
|
||||
// {
|
||||
// //f->AddOverlayNumber(0);
|
||||
// //if (frame >= 1 && frame <= 22)
|
||||
// // f->DisplayWaveform();
|
||||
//
|
||||
// // Write frame
|
||||
// //cout << "queue frame " << frame << endl;
|
||||
// cout << "queue frame " << frame << " (" << f->number << ", " << f << ")" << endl;
|
||||
// w.WriteFrame(f);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Write Footer
|
||||
// w.WriteTrailer();
|
||||
//
|
||||
// // Close writer & reader
|
||||
// w.Close();
|
||||
//
|
||||
// // Close timeline
|
||||
// t.Close();
|
||||
//
|
||||
// cout << "Successfully Finished Timeline DEMO" << endl;
|
||||
// return 0;
|
||||
|
||||
|
||||
|
||||
@@ -167,7 +149,7 @@ int main()
|
||||
// openshot::FFmpegReader r("../../src/examples/piano.wav");
|
||||
// openshot::FFmpegReader r("/home/jonathan/Videos/big-buck-bunny_trailer.webm");
|
||||
|
||||
openshot::FFmpegReader r1("/home/jonathan/Videos/sintel-1024-stereo.mp4");
|
||||
openshot::FFmpegReader r("/home/jonathan/Desktop/test2.flv");
|
||||
// openshot::FFmpegReader r("/home/jonathan/Videos/OpenShot_Now_In_3d.mp4");
|
||||
// openshot::FFmpegReader r("/home/jonathan/Videos/sintel_trailer-720p.mp4");
|
||||
// openshot::FFmpegReader r("/home/jonathan/Aptana Studio Workspace/OpenShotLibrary/src/examples/piano.wav");
|
||||
@@ -177,65 +159,78 @@ int main()
|
||||
// openshot::FFmpegReader r("/home/jonathan/Aptana Studio Workspace/OpenShotLibrary/src/examples/asdf.wdf");
|
||||
|
||||
|
||||
// openshot::FrameMapper r(&r1, Framerate(30,1), PULLDOWN_CLASSIC);
|
||||
//
|
||||
// // Display debug info
|
||||
// r.Open();
|
||||
// r.DisplayInfo();
|
||||
//
|
||||
// // Create a writer
|
||||
// FFmpegWriter w("/home/jonathan/output.webm");
|
||||
// w.DisplayInfo();
|
||||
//
|
||||
// // Set options
|
||||
// w.SetAudioOptions(true, "libvorbis", 44100, 2, 128000, false);
|
||||
// w.SetVideoOptions(true, "libvpx", Fraction(30, 1), 640, 360, Fraction(1,1), false, false, 2000000);
|
||||
//
|
||||
// // Prepare Streams
|
||||
// w.PrepareStreams();
|
||||
//
|
||||
// // Set Options
|
||||
//// w.SetOption(VIDEO_STREAM, "quality", "good");
|
||||
//// w.SetOption(VIDEO_STREAM, "g", "120");
|
||||
//// w.SetOption(VIDEO_STREAM, "qmin", "11");
|
||||
//// w.SetOption(VIDEO_STREAM, "qmax", "51");
|
||||
//// w.SetOption(VIDEO_STREAM, "profile", "0");
|
||||
//// w.SetOption(VIDEO_STREAM, "speed", "0");
|
||||
//// w.SetOption(VIDEO_STREAM, "level", "216");
|
||||
//// w.SetOption(VIDEO_STREAM, "rc_lookahead", "16");
|
||||
//// w.SetOption(VIDEO_STREAM, "rc_min_rate", "100000");
|
||||
//// w.SetOption(VIDEO_STREAM, "rc_max_rate", "24000000");
|
||||
//// w.SetOption(VIDEO_STREAM, "slices", "4");
|
||||
//// w.SetOption(VIDEO_STREAM, "arnr_max_frames", "7");
|
||||
//// w.SetOption(VIDEO_STREAM, "arnr_strength", "5");
|
||||
//// w.SetOption(VIDEO_STREAM, "arnr_type", "3");
|
||||
//
|
||||
// // Write header
|
||||
// w.WriteHeader();
|
||||
//
|
||||
// // Output stream info
|
||||
// w.OutputStreamInfo();
|
||||
//
|
||||
// //Frame *f = r.GetFrame(1);
|
||||
//
|
||||
// //for (int frame = 131; frame >= 1; frame--)
|
||||
// for (int frame = 1; frame <= 500; frame++)
|
||||
|
||||
// Display debug info
|
||||
r.Open();
|
||||
r.DisplayInfo();
|
||||
|
||||
// for (int frame = 1; frame <= 300; frame++)
|
||||
// {
|
||||
// tr1::shared_ptr<Frame> f = r.GetFrame(frame);
|
||||
// //f->AddOverlayNumber(0);
|
||||
// //f->Display();
|
||||
//
|
||||
// // Write frame
|
||||
// cout << "queue frame " << frame << endl;
|
||||
// w.WriteFrame(f);
|
||||
// }
|
||||
//
|
||||
// // Write Footer
|
||||
// w.WriteTrailer();
|
||||
//
|
||||
// // Close writer & reader
|
||||
// w.Close();
|
||||
// r.Close();
|
||||
// return 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Create a writer
|
||||
FFmpegWriter w("/home/jonathan/output.mp4");
|
||||
w.DisplayInfo();
|
||||
|
||||
// Set options
|
||||
//w.SetAudioOptions(true, "libvorbis", 44100, 2, 128000, false);
|
||||
w.SetAudioOptions(true, "libmp3lame", 44100, 2, 128000, false);
|
||||
|
||||
//w.SetVideoOptions(true, "libvpx", Fraction(25,1), 320, 240, Fraction(1,1), false, false, 2000000);
|
||||
w.SetVideoOptions(true, "libx264", Fraction(25,1), 320, 240, Fraction(1,1), false, false, 2000000);
|
||||
//w.SetVideoOptions(true, "libtheora", Fraction(25,1), 320, 240, Fraction(1,1), false, false, 2000000);
|
||||
|
||||
// Prepare Streams
|
||||
w.PrepareStreams();
|
||||
|
||||
// Set Options
|
||||
// w.SetOption(VIDEO_STREAM, "quality", "good");
|
||||
// w.SetOption(VIDEO_STREAM, "g", "120");
|
||||
// w.SetOption(VIDEO_STREAM, "qmin", "11");
|
||||
// w.SetOption(VIDEO_STREAM, "qmax", "51");
|
||||
// w.SetOption(VIDEO_STREAM, "profile", "0");
|
||||
// w.SetOption(VIDEO_STREAM, "speed", "0");
|
||||
// w.SetOption(VIDEO_STREAM, "level", "216");
|
||||
// w.SetOption(VIDEO_STREAM, "rc_lookahead", "16");
|
||||
// w.SetOption(VIDEO_STREAM, "rc_min_rate", "100000");
|
||||
// w.SetOption(VIDEO_STREAM, "rc_max_rate", "24000000");
|
||||
// w.SetOption(VIDEO_STREAM, "slices", "4");
|
||||
// w.SetOption(VIDEO_STREAM, "arnr_max_frames", "7");
|
||||
// w.SetOption(VIDEO_STREAM, "arnr_strength", "5");
|
||||
// w.SetOption(VIDEO_STREAM, "arnr_type", "3");
|
||||
|
||||
// Write header
|
||||
w.WriteHeader();
|
||||
|
||||
// Output stream info
|
||||
w.OutputStreamInfo();
|
||||
|
||||
//Frame *f = r.GetFrame(1);
|
||||
|
||||
//for (int frame = 131; frame >= 1; frame--)
|
||||
for (int frame = 1; frame <= 300; frame++)
|
||||
{
|
||||
tr1::shared_ptr<Frame> f = r.GetFrame(frame);
|
||||
//f->AddOverlayNumber(0);
|
||||
//f->Display();
|
||||
|
||||
// Write frame
|
||||
cout << "queue frame " << frame << endl;
|
||||
w.WriteFrame(f);
|
||||
}
|
||||
|
||||
// Write Footer
|
||||
w.WriteTrailer();
|
||||
|
||||
// Close writer & reader
|
||||
w.Close();
|
||||
r.Close();
|
||||
|
||||
|
||||
cout << "Successfully executed Main.cpp!" << endl;
|
||||
|
||||
Reference in New Issue
Block a user