Merge branch 'develop' into albumartfixes

This commit is contained in:
FeRD (Frank Dana)
2020-10-19 16:40:47 -04:00
198 changed files with 2403 additions and 1499 deletions

View File

@@ -31,7 +31,10 @@
* along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../include/FFmpegReader.h"
#include "FFmpegReader.h"
#include <thread> // for std::this_thread::sleep_for
#include <chrono> // for std::chrono::milliseconds
#define ENABLE_VAAPI 0
@@ -83,7 +86,7 @@ int hw_de_on = 0;
AVHWDeviceType hw_de_av_device_type_global = AV_HWDEVICE_TYPE_NONE;
#endif
FFmpegReader::FFmpegReader(std::string path)
FFmpegReader::FFmpegReader(const std::string& path, bool inspect_reader)
: last_frame(0), is_seeking(0), seeking_pts(0), seeking_frame(0), seek_count(0),
audio_pts_offset(99999), video_pts_offset(99999), path(path), is_video_seek(true), check_interlace(false),
check_fps(false), enable_seek(true), is_open(false), seek_audio_frame_found(0), seek_video_frame_found(0),
@@ -91,27 +94,11 @@ FFmpegReader::FFmpegReader(std::string path)
current_video_frame(0), has_missing_frames(false), num_packets_since_video_frame(0), num_checks_since_final(0),
packet(NULL) {
// Initialize FFMpeg, and register all formats and codecs
AV_REGISTER_ALL
AVCODEC_REGISTER_ALL
// Init cache
working_cache.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * info.fps.ToDouble() * 2, info.width, info.height, info.sample_rate, info.channels);
missing_frames.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * 2, info.width, info.height, info.sample_rate, info.channels);
final_cache.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * 2, info.width, info.height, info.sample_rate, info.channels);
// Open and Close the reader, to populate its attributes (such as height, width, etc...)
Open();
Close();
}
FFmpegReader::FFmpegReader(std::string path, bool inspect_reader)
: last_frame(0), is_seeking(0), seeking_pts(0), seeking_frame(0), seek_count(0),
audio_pts_offset(99999), video_pts_offset(99999), path(path), is_video_seek(true), check_interlace(false),
check_fps(false), enable_seek(true), is_open(false), seek_audio_frame_found(0), seek_video_frame_found(0),
prev_samples(0), prev_pts(0), pts_total(0), pts_counter(0), is_duration_known(false), largest_frame_processed(0),
current_video_frame(0), has_missing_frames(false), num_packets_since_video_frame(0), num_checks_since_final(0),
packet(NULL) {
// Configure OpenMP parallelism
// Default number of threads per section
omp_set_num_threads(OPEN_MP_NUM_PROCESSORS);
// Allow nested parallel sections as deeply as supported
omp_set_max_active_levels(OPEN_MP_MAX_ACTIVE);
// Initialize FFMpeg, and register all formats and codecs
AV_REGISTER_ALL
@@ -911,11 +898,6 @@ std::shared_ptr<Frame> FFmpegReader::ReadStream(int64_t requested_frame) {
int minimum_packets = OPEN_MP_NUM_PROCESSORS;
int max_packets = 4096;
// Set the number of threads in OpenMP
omp_set_num_threads(OPEN_MP_NUM_PROCESSORS);
// Allow nested OpenMP sections
omp_set_nested(true);
// Debug output
ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ReadStream", "requested_frame", requested_frame, "OPEN_MP_NUM_PROCESSORS", OPEN_MP_NUM_PROCESSORS);
@@ -938,7 +920,7 @@ std::shared_ptr<Frame> FFmpegReader::ReadStream(int64_t requested_frame) {
// Wait if too many frames are being processed
while (processing_video_frames_size + processing_audio_frames_size >= minimum_packets) {
usleep(2500);
std::this_thread::sleep_for(std::chrono::milliseconds(3));
const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
processing_video_frames_size = processing_video_frames.size();
processing_audio_frames_size = processing_audio_frames.size();
@@ -1306,7 +1288,7 @@ void FFmpegReader::ProcessVideoPacket(int64_t requested_frame) {
if (max_height <= 0)
max_height = info.height;
Clip *parent = (Clip *) GetClip();
Clip *parent = (Clip *) GetParentClip();
if (parent) {
if (parent->scale == SCALE_FIT || parent->scale == SCALE_STRETCH) {
// Best fit or Stretch scaling (based on max timeline size * scaling keyframes)
@@ -1729,7 +1711,7 @@ void FFmpegReader::Seek(int64_t requested_frame) {
// Wait for any processing frames to complete
while (processing_video_frames_size + processing_audio_frames_size > 0) {
usleep(2500);
std::this_thread::sleep_for(std::chrono::milliseconds(3));
const GenericScopedLock <CriticalSection> lock(processingCriticalSection);
processing_video_frames_size = processing_video_frames.size();
processing_audio_frames_size = processing_audio_frames.size();
@@ -1878,8 +1860,20 @@ void FFmpegReader::UpdatePTSOffset(bool is_video) {
// VIDEO PACKET
if (video_pts_offset == 99999) // Has the offset been set yet?
{
// Find the difference between PTS and frame number (no more than 10 timebase units allowed)
video_pts_offset = 0 - std::max(GetVideoPTS(), (int64_t) info.video_timebase.ToInt() * 10);
// Find the difference between PTS and frame number
video_pts_offset = 0 - GetVideoPTS();
// Find the difference between PTS and frame number
// Also, determine if PTS is invalid (too far away from zero)
// We compare the PTS to the timebase value equal to 1 second (which means the PTS
// must be within the -1 second to +1 second of zero, otherwise we ignore it)
// TODO: Please see https://github.com/OpenShot/libopenshot/pull/565#issuecomment-690985272
// for ideas to improve this logic.
int64_t max_offset = info.video_timebase.Reciprocal().ToFloat();
if (video_pts_offset < -max_offset || video_pts_offset > max_offset) {
// Ignore PTS, it seems invalid
video_pts_offset = 0;
}
// debug output
ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::UpdatePTSOffset (Video)", "video_pts_offset", video_pts_offset, "is_video", is_video);
@@ -1888,8 +1882,18 @@ void FFmpegReader::UpdatePTSOffset(bool is_video) {
// AUDIO PACKET
if (audio_pts_offset == 99999) // Has the offset been set yet?
{
// Find the difference between PTS and frame number (no more than 10 timebase units allowed)
audio_pts_offset = 0 - std::max(packet->pts, (int64_t) info.audio_timebase.ToInt() * 10);
// Find the difference between PTS and frame number
// Also, determine if PTS is invalid (too far away from zero)
// We compare the PTS to the timebase value equal to 1 second (which means the PTS
// must be within the -1 second to +1 second of zero, otherwise we ignore it)
// TODO: Please see https://github.com/OpenShot/libopenshot/pull/565#issuecomment-690985272
// for ideas to improve this logic.
audio_pts_offset = 0 - packet->pts;
int64_t max_offset = info.audio_timebase.Reciprocal().ToFloat();
if (audio_pts_offset < -max_offset || audio_pts_offset > max_offset) {
// Ignore PTS, it seems invalid
audio_pts_offset = 0;
}
// debug output
ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::UpdatePTSOffset (Audio)", "audio_pts_offset", audio_pts_offset, "is_video", is_video);
@@ -2145,7 +2149,7 @@ bool FFmpegReader::CheckMissingFrame(int64_t requested_frame) {
// Add this frame to the processed map (since it's already done)
std::shared_ptr<QImage> parent_image = parent_frame->GetImage();
if (parent_image) {
missing_frame->AddImage(std::shared_ptr<QImage>(new QImage(*parent_image)));
missing_frame->AddImage(std::make_shared<QImage>(*parent_image));
processed_video_frames[missing_frame->number] = missing_frame->number;
}
}
@@ -2235,7 +2239,7 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream, int64_t requested_fram
if (info.has_video && !is_video_ready && last_video_frame) {
// Copy image from last frame
f->AddImage(std::shared_ptr<QImage>(new QImage(*last_video_frame->GetImage())));
f->AddImage(std::make_shared<QImage>(*last_video_frame->GetImage()));
is_video_ready = true;
}
@@ -2257,7 +2261,7 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream, int64_t requested_fram
// Add missing image (if needed - sometimes end_of_stream causes frames with only audio)
if (info.has_video && !is_video_ready && last_video_frame)
// Copy image from last frame
f->AddImage(std::shared_ptr<QImage>(new QImage(*last_video_frame->GetImage())));
f->AddImage(std::make_shared<QImage>(*last_video_frame->GetImage()));
// Reset counter since last 'final' frame
num_checks_since_final = 0;