You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
1) Reduced all openmp to use /2 the available CPUs (for performance reasons)
2) Improved detection of pixel format (enabled GIF support.. although it is still flawed a bit) 3) Improved error reporting when video encoding issues happen
This commit is contained in:
@@ -40,6 +40,8 @@
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#include <libavutil/mathematics.h>
|
||||
#include <libavutil/pixfmt.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
|
||||
// libavutil changed folders at some point
|
||||
#if LIBAVFORMAT_VERSION_MAJOR >= 53
|
||||
|
||||
@@ -159,7 +159,7 @@ void FFmpegReader::Open() throw(InvalidFile, NoStreamsFound, InvalidCodec)
|
||||
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
|
||||
|
||||
// Set number of threads equal to number of processors + 1
|
||||
pCodecCtx->thread_count = omp_get_num_procs();
|
||||
pCodecCtx->thread_count = omp_get_num_procs() / 2;
|
||||
|
||||
// Find the decoder for the video stream
|
||||
AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
|
||||
@@ -188,7 +188,7 @@ void FFmpegReader::Open() throw(InvalidFile, NoStreamsFound, InvalidCodec)
|
||||
aCodecCtx = pFormatCtx->streams[audioStream]->codec;
|
||||
|
||||
// Set number of threads equal to number of processors + 1
|
||||
aCodecCtx->thread_count = omp_get_num_procs();
|
||||
aCodecCtx->thread_count = omp_get_num_procs() / 2;
|
||||
|
||||
// Find the decoder for the audio stream
|
||||
AVCodec *aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
|
||||
|
||||
@@ -341,7 +341,7 @@ void FFmpegWriter::write_queued_frames()
|
||||
spooled_video_frames.clear();
|
||||
spooled_audio_frames.clear();
|
||||
|
||||
omp_set_num_threads(4);
|
||||
omp_set_num_threads(omp_get_num_procs() / 2);
|
||||
omp_set_nested(true);
|
||||
#pragma omp parallel
|
||||
{
|
||||
@@ -410,10 +410,9 @@ void FFmpegWriter::write_queued_frames()
|
||||
// Get AVFrame
|
||||
AVFrame *av_frame = av_frames[frame];
|
||||
|
||||
// deallocate AVFrame
|
||||
// deallocate AVPicture and AVFrame
|
||||
av_free(av_frame->data[0]);
|
||||
av_free(av_frame);
|
||||
|
||||
av_frames.erase(frame);
|
||||
}
|
||||
|
||||
@@ -812,21 +811,49 @@ AVStream* FFmpegWriter::add_video_stream()
|
||||
c->time_base.num = info.video_timebase.num;
|
||||
c->time_base.den = info.video_timebase.den;
|
||||
c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */
|
||||
c->pix_fmt = PIX_FMT_YUV420P;
|
||||
if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
|
||||
if (c->codec_id == CODEC_ID_MPEG2VIDEO)
|
||||
/* just for testing, we also add B frames */
|
||||
c->max_b_frames = 2;
|
||||
}
|
||||
if (c->codec_id == CODEC_ID_MPEG1VIDEO) {
|
||||
if (c->codec_id == CODEC_ID_MPEG1VIDEO)
|
||||
/* Needed to avoid using macroblocks in which some coeffs overflow.
|
||||
This does not happen with normal video, it just happens here as
|
||||
the motion of the chroma plane does not match the luma plane. */
|
||||
c->mb_decision = 2;
|
||||
}
|
||||
// some formats want stream headers to be separate
|
||||
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
|
||||
// Find all supported pixel formats for this codec
|
||||
const PixelFormat* supported_pixel_formats = codec->pix_fmts;
|
||||
while (supported_pixel_formats != NULL && *supported_pixel_formats != PIX_FMT_NONE) {
|
||||
cout << "supported pixel format: " << av_get_pix_fmt_name(*supported_pixel_formats) << endl;
|
||||
// Assign the 1st valid pixel format (if one is missing)
|
||||
if (c->pix_fmt == PIX_FMT_NONE)
|
||||
c->pix_fmt = *supported_pixel_formats;
|
||||
++supported_pixel_formats;
|
||||
}
|
||||
|
||||
// Codec doesn't have any pix formats?
|
||||
if (c->pix_fmt == PIX_FMT_NONE) {
|
||||
if(fmt->video_codec == CODEC_ID_RAWVIDEO) {
|
||||
// Raw video should use RGB24
|
||||
c->pix_fmt = PIX_FMT_RGB24;
|
||||
// Set raw picture flag (so we don't encode this video)
|
||||
oc->oformat->flags |= AVFMT_RAWPICTURE;
|
||||
} else {
|
||||
// Set the default codec
|
||||
c->pix_fmt = PIX_FMT_YUV420P;
|
||||
}
|
||||
}
|
||||
|
||||
// Override Gif Support (TODO: Find a better way to accomplish this)
|
||||
if (c->codec_id == CODEC_ID_GIF) {
|
||||
// Force rgb24 which seems to be required for GIF
|
||||
c->pix_fmt = PIX_FMT_RGB24;
|
||||
// Set raw picture flag (so we don't encode the image)
|
||||
oc->oformat->flags |= AVFMT_RAWPICTURE;
|
||||
}
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
@@ -837,7 +864,7 @@ void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st)
|
||||
audio_codec = st->codec;
|
||||
|
||||
// Set number of threads equal to number of processors + 1
|
||||
audio_codec->thread_count = omp_get_num_procs();
|
||||
audio_codec->thread_count = omp_get_num_procs() / 2;
|
||||
|
||||
// Find the audio encoder
|
||||
codec = avcodec_find_encoder(audio_codec->codec_id);
|
||||
@@ -888,7 +915,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st)
|
||||
video_codec = st->codec;
|
||||
|
||||
// Set number of threads equal to number of processors + 1
|
||||
video_codec->thread_count = omp_get_num_procs();
|
||||
video_codec->thread_count = omp_get_num_procs() / 2;
|
||||
|
||||
/* find the video encoder */
|
||||
codec = avcodec_find_encoder(video_codec->codec_id);
|
||||
@@ -1166,15 +1193,24 @@ void FFmpegWriter::process_video_packet(tr1::shared_ptr<Frame> frame)
|
||||
frame_source = allocate_avframe(PIX_FMT_RGB24, source_image_width, source_image_height, &bytes_source);
|
||||
AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt, info.width, info.height, &bytes_final);
|
||||
|
||||
// Determine how many colors we are copying (3 or 4)
|
||||
int step = 3; // rgb
|
||||
if ( video_st->codec->pix_fmt == PIX_FMT_RGBA || video_st->codec->pix_fmt == PIX_FMT_ARGB || video_st->codec->pix_fmt == PIX_FMT_BGRA )
|
||||
step = 4; // rgba
|
||||
|
||||
// Fill the AVFrame with RGB image data
|
||||
int source_total_pixels = source_image_width * source_image_height;
|
||||
for (int packet = 0, row = 0; packet < source_total_pixels; packet++, row+=3)
|
||||
for (int packet = 0, row = 0; packet < source_total_pixels; packet++, row+=step)
|
||||
{
|
||||
// Update buffer (which is already linked to the AVFrame: pFrameRGB)
|
||||
// Each color needs to be 8 bit (so I'm bit shifting the 16 bit ints)
|
||||
frame_source->data[0][row] = pixel_packets[packet].red >> 8;
|
||||
frame_source->data[0][row+1] = pixel_packets[packet].green >> 8;
|
||||
frame_source->data[0][row+2] = pixel_packets[packet].blue >> 8;
|
||||
|
||||
// Copy alpha channel (if needed)
|
||||
if (step == 4)
|
||||
frame_source->data[0][row+3] = pixel_packets[packet].opacity >> 8;
|
||||
}
|
||||
|
||||
// Resize & convert pixel format
|
||||
@@ -1203,7 +1239,7 @@ void FFmpegWriter::write_video_packet(tr1::shared_ptr<Frame> frame, AVFrame* fra
|
||||
|
||||
pkt.flags |= AV_PKT_FLAG_KEY;
|
||||
pkt.stream_index= video_st->index;
|
||||
pkt.data= (uint8_t *)frame_final;
|
||||
pkt.data= (uint8_t*)frame_final;
|
||||
pkt.size= sizeof(AVPicture);
|
||||
|
||||
// Increment PTS (in frames and scaled to the codec's timebase)
|
||||
@@ -1215,6 +1251,7 @@ void FFmpegWriter::write_video_packet(tr1::shared_ptr<Frame> frame, AVFrame* fra
|
||||
if (error_code != 0)
|
||||
{
|
||||
string error_description = av_err2str(error_code);
|
||||
cout << "error: " << error_code << ": " << error_description << endl;
|
||||
throw ErrorEncodingVideo("Error while writing raw video frame", frame->number);
|
||||
}
|
||||
|
||||
|
||||
18
src/Main.cpp
18
src/Main.cpp
@@ -40,6 +40,8 @@ using namespace tr1;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
/*
|
||||
|
||||
FFmpegReader sinelReader("/home/jonathan/Videos/sintel_trailer-720p.mp4");
|
||||
sinelReader.Open();
|
||||
|
||||
@@ -89,6 +91,8 @@ int main(int argc, char* argv[])
|
||||
//c1.GetFrame(150)->Save("test.bmp", 1.0);
|
||||
return 0;
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// SDLPlayer p;
|
||||
// p.Reader(&r2);
|
||||
@@ -112,12 +116,12 @@ int main(int argc, char* argv[])
|
||||
|
||||
|
||||
// Reader
|
||||
FFmpegReader r1("/home/jonathan/colors-24-converted-to-29-97-fps-pulldown-advanced.mp4");
|
||||
FFmpegReader r1("/home/jonathan/Videos/New_OpenShot_Timeline.webm");
|
||||
r1.Open();
|
||||
|
||||
// FrameMapper
|
||||
FrameMapper r(&r1, Fraction(24,1), PULLDOWN_ADVANCED);
|
||||
r.PrintMapping();
|
||||
//FrameMapper r(&r1, Fraction(24,1), PULLDOWN_ADVANCED);
|
||||
//r.PrintMapping();
|
||||
|
||||
/* WRITER ---------------- */
|
||||
FFmpegWriter w("/home/jonathan/output.mp4");
|
||||
@@ -126,7 +130,7 @@ int main(int argc, char* argv[])
|
||||
//w.SetAudioOptions(true, "libvorbis", 48000, 2, 188000);
|
||||
//w.SetAudioOptions(true, "libmp3lame", 44100, 2, 128000);
|
||||
//w.SetVideoOptions(true, "libvpx", Fraction(24,1), 1280, 720, Fraction(1,1), false, false, 30000000);
|
||||
w.SetVideoOptions(true, "mpeg4", r.info.fps, 1280, 720, Fraction(1,1), false, false, 3000000);
|
||||
w.SetVideoOptions(true, "mpeg4", openshot::Fraction(3,1), 720, 360, Fraction(1,1), false, false, 3000000);
|
||||
|
||||
// Prepare Streams
|
||||
w.PrepareStreams();
|
||||
@@ -138,7 +142,7 @@ int main(int argc, char* argv[])
|
||||
w.OutputStreamInfo();
|
||||
|
||||
//for (int frame = 3096; frame <= 3276; frame++)
|
||||
for (int frame = 1; frame <= 20; frame++)
|
||||
for (int frame = 1; frame <= 100; frame++)
|
||||
{
|
||||
// tr1::shared_ptr<Frame> f(new Frame(frame, 1280, 720, "#000000", 44100, 2));
|
||||
// if (frame % 2 == 0)
|
||||
@@ -150,7 +154,7 @@ int main(int argc, char* argv[])
|
||||
// cout << f->number << endl;
|
||||
// w.WriteFrame(f);
|
||||
|
||||
tr1::shared_ptr<Frame> f = r.GetFrame(frame);
|
||||
tr1::shared_ptr<Frame> f = r1.GetFrame(frame);
|
||||
if (f)
|
||||
{
|
||||
//if (frame >= 250)
|
||||
@@ -159,7 +163,7 @@ int main(int argc, char* argv[])
|
||||
//f->Display();
|
||||
|
||||
// Write frame
|
||||
f->Display();
|
||||
//f->Display();
|
||||
cout << "queue frame " << frame << " (" << f->number << ", " << f << ")" << endl;
|
||||
w.WriteFrame(f);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user