You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
Better detection of duration, especially for audio-only files. Improved PTS offset detection (for when start_time is used), mainly things recorded from streams. Better bitrate detection as well.
This commit is contained in:
@@ -645,14 +645,29 @@ void FFmpegReader::UpdateAudioInfo() {
|
||||
info.channel_layout = (ChannelLayout) AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout;
|
||||
info.sample_rate = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->sample_rate;
|
||||
info.audio_bit_rate = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->bit_rate;
|
||||
if (info.audio_bit_rate <= 0) {
|
||||
// Get bitrate from format
|
||||
info.audio_bit_rate = pFormatCtx->bit_rate;
|
||||
}
|
||||
|
||||
// Set audio timebase
|
||||
info.audio_timebase.num = aStream->time_base.num;
|
||||
info.audio_timebase.den = aStream->time_base.den;
|
||||
|
||||
// Get timebase of audio stream (if valid) and greater than the current duration
|
||||
if (aStream->duration > 0.0f && aStream->duration > info.duration)
|
||||
info.duration = aStream->duration * info.audio_timebase.ToDouble();
|
||||
if (aStream->duration > 0 && aStream->duration > info.duration) {
|
||||
// Get duration from audio stream
|
||||
info.duration = aStream->duration * info.audio_timebase.ToDouble();
|
||||
} else if (pFormatCtx->duration > 0 && info.duration <= 0.0f) {
|
||||
// Use the format's duration
|
||||
info.duration = float(pFormatCtx->duration) / AV_TIME_BASE;
|
||||
}
|
||||
|
||||
// Calculate duration from filesize and bitrate (if any)
|
||||
if (info.duration <= 0.0f && info.video_bit_rate > 0 && info.file_size > 0) {
|
||||
// Estimate from bitrate, total bytes, and framerate
|
||||
info.duration = float(info.file_size) / info.video_bit_rate;
|
||||
}
|
||||
|
||||
// Check for an invalid video length
|
||||
if (info.has_video && info.video_length <= 0) {
|
||||
@@ -767,14 +782,16 @@ void FFmpegReader::UpdateVideoInfo() {
|
||||
info.duration = pStream->duration * info.video_timebase.ToDouble();
|
||||
|
||||
// Check for valid duration (if found)
|
||||
if (info.duration <= 0.0f && pFormatCtx->duration >= 0)
|
||||
// Use the format's duration
|
||||
info.duration = float(pFormatCtx->duration) / AV_TIME_BASE;
|
||||
if (info.duration <= 0.0f && pFormatCtx->duration >= 0) {
|
||||
// Use the format's duration
|
||||
info.duration = float(pFormatCtx->duration) / AV_TIME_BASE;
|
||||
}
|
||||
|
||||
// Calculate duration from filesize and bitrate (if any)
|
||||
if (info.duration <= 0.0f && info.video_bit_rate > 0 && info.file_size > 0)
|
||||
// Estimate from bitrate, total bytes, and framerate
|
||||
info.duration = float(info.file_size) / info.video_bit_rate;
|
||||
if (info.duration <= 0.0f && info.video_bit_rate > 0 && info.file_size > 0) {
|
||||
// Estimate from bitrate, total bytes, and framerate
|
||||
info.duration = float(info.file_size) / info.video_bit_rate;
|
||||
}
|
||||
|
||||
// No duration found in stream of file
|
||||
if (info.duration <= 0.0f) {
|
||||
@@ -1268,7 +1285,7 @@ void FFmpegReader::ProcessVideoPacket(int64_t requested_frame) {
|
||||
max_width = std::max(float(max_width), max_width * max_scale_x);
|
||||
max_height = std::max(float(max_height), max_height * max_scale_y);
|
||||
|
||||
} else if (parent->scale == SCALE_CROP) {
|
||||
} else if (parent->scale == SCALE_CROP) {
|
||||
// Cropping scale mode (based on max timeline size * cropped size * scaling keyframes)
|
||||
float max_scale_x = parent->scale_x.GetMaxPoint().co.Y;
|
||||
float max_scale_y = parent->scale_y.GetMaxPoint().co.Y;
|
||||
@@ -1843,20 +1860,25 @@ 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
|
||||
video_pts_offset = 0 - GetVideoPTS();
|
||||
if (pStream->start_time != AV_NOPTS_VALUE && pStream->start_time > 0) {
|
||||
// Adjust all PTS by start_time (if available)
|
||||
video_pts_offset = 0 - pStream->start_time;
|
||||
} else {
|
||||
// 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;
|
||||
}
|
||||
// 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);
|
||||
@@ -1871,11 +1893,19 @@ void FFmpegReader::UpdatePTSOffset(bool is_video) {
|
||||
// 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;
|
||||
if (aStream->start_time != AV_NOPTS_VALUE && aStream->start_time > 0) {
|
||||
// Adjust all PTS by start_time (if available)
|
||||
audio_pts_offset = 0 - aStream->start_time;
|
||||
} else {
|
||||
// Determine if PTS is sane
|
||||
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
|
||||
// Assuming the start_time is not set or not valid, then the PTS should be near the
|
||||
// beginning of the stream
|
||||
audio_pts_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// debug output
|
||||
|
||||
Reference in New Issue
Block a user