Merge pull request #661 from ferdnyc/redirect-print-fxns

Make console-output functions redirectable; add operator<< for Fraction, Point, Coordinate; new KeyFrame::PrintPoints & PrintValues with unit tests
This commit is contained in:
Frank Dana
2021-09-26 23:16:49 -04:00
committed by GitHub
27 changed files with 743 additions and 351 deletions

View File

@@ -28,6 +28,10 @@
* along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cmath>
#include <iostream>
#include <iomanip>
#include "FrameMapper.h"
#include "Exceptions.h"
#include "Clip.h"
@@ -517,7 +521,7 @@ std::shared_ptr<Frame> FrameMapper::GetFrame(int64_t requested_frame)
copy_samples.sample_end += EXTRA_INPUT_SAMPLES;
int samples_per_end_frame =
Frame::GetSamplesPerFrame(copy_samples.frame_end, original,
reader->info.sample_rate, reader->info.channels);
reader->info.sample_rate, reader->info.channels);
if (copy_samples.sample_end >= samples_per_end_frame)
{
// check for wrapping
@@ -533,7 +537,7 @@ std::shared_ptr<Frame> FrameMapper::GetFrame(int64_t requested_frame)
copy_samples.sample_start += EXTRA_INPUT_SAMPLES;
int samples_per_start_frame =
Frame::GetSamplesPerFrame(copy_samples.frame_start, original,
reader->info.sample_rate, reader->info.channels);
reader->info.sample_rate, reader->info.channels);
if (copy_samples.sample_start >= samples_per_start_frame)
{
// check for wrapping
@@ -611,7 +615,7 @@ std::shared_ptr<Frame> FrameMapper::GetFrame(int64_t requested_frame)
return final_cache.GetFrame(requested_frame);
}
void FrameMapper::PrintMapping()
void FrameMapper::PrintMapping(std::ostream* out)
{
// Check if mappings are dirty (and need to be recalculated)
if (is_dirty)
@@ -622,8 +626,16 @@ void FrameMapper::PrintMapping()
for (float map = 1; map <= frames.size(); map++)
{
MappedFrame frame = frames[map - 1];
cout << "Target frame #: " << map << " mapped to original frame #:\t(" << frame.Odd.Frame << " odd, " << frame.Even.Frame << " even)" << endl;
cout << " - Audio samples mapped to frame " << frame.Samples.frame_start << ":" << frame.Samples.sample_start << " to frame " << frame.Samples.frame_end << ":" << frame.Samples.sample_end << endl;
*out << "Target frame #: " << map
<< " mapped to original frame #:\t("
<< frame.Odd.Frame << " odd, "
<< frame.Even.Frame << " even)" << std::endl;
*out << " - Audio samples mapped to frame "
<< frame.Samples.frame_start << ":"
<< frame.Samples.sample_start << " to frame "
<< frame.Samples.frame_end << ":"
<< frame.Samples.sample_end << endl;
}
}
@@ -733,7 +745,14 @@ void FrameMapper::SetJsonValue(const Json::Value root) {
// Change frame rate or audio mapping details
void FrameMapper::ChangeMapping(Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout)
{
ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ChangeMapping", "target_fps.num", target_fps.num, "target_fps.den", target_fps.den, "target_pulldown", target_pulldown, "target_sample_rate", target_sample_rate, "target_channels", target_channels, "target_channel_layout", target_channel_layout);
ZmqLogger::Instance()->AppendDebugMethod(
"FrameMapper::ChangeMapping",
"target_fps.num", target_fps.num,
"target_fps.den", target_fps.den,
"target_pulldown", target_pulldown,
"target_sample_rate", target_sample_rate,
"target_channels", target_channels,
"target_channel_layout", target_channel_layout);
// Mark as dirty
is_dirty = true;
@@ -779,7 +798,13 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t orig
int samples_in_frame = frame->GetAudioSamplesCount();
ChannelLayout channel_layout_in_frame = frame->ChannelsLayout();
ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio", "frame->number", frame->number, "original_frame_number", original_frame_number, "channels_in_frame", channels_in_frame, "samples_in_frame", samples_in_frame, "sample_rate_in_frame", sample_rate_in_frame);
ZmqLogger::Instance()->AppendDebugMethod(
"FrameMapper::ResampleMappedAudio",
"frame->number", frame->number,
"original_frame_number", original_frame_number,
"channels_in_frame", channels_in_frame,
"samples_in_frame", samples_in_frame,
"sample_rate_in_frame", sample_rate_in_frame);
// Get audio sample array
float* frame_samples_float = NULL;
@@ -815,7 +840,14 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t orig
delete[] frame_samples_float;
frame_samples_float = NULL;
ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (got sample data from frame)", "frame->number", frame->number, "total_frame_samples", total_frame_samples, "target channels", info.channels, "channels_in_frame", channels_in_frame, "target sample_rate", info.sample_rate, "samples_in_frame", samples_in_frame);
ZmqLogger::Instance()->AppendDebugMethod(
"FrameMapper::ResampleMappedAudio (got sample data from frame)",
"frame->number", frame->number,
"total_frame_samples", total_frame_samples,
"target channels", info.channels,
"channels_in_frame", channels_in_frame,
"target sample_rate", info.sample_rate,
"samples_in_frame", samples_in_frame);
// Create input frame (and allocate arrays)
@@ -823,8 +855,10 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t orig
AV_RESET_FRAME(audio_frame);
audio_frame->nb_samples = total_frame_samples / channels_in_frame;
int error_code = avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) frame_samples,
audio_frame->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * channels_in_frame, 1);
int buf_size = audio_frame->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * channels_in_frame;
int error_code = avcodec_fill_audio_frame(
audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16,
(uint8_t *) frame_samples, buf_size, 1);
if (error_code < 0)
{
@@ -837,7 +871,14 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t orig
// Update total samples & input frame size (due to bigger or smaller data types)
total_frame_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame->number), target, info.sample_rate, info.channels);
ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (adjust # of samples)", "total_frame_samples", total_frame_samples, "info.sample_rate", info.sample_rate, "sample_rate_in_frame", sample_rate_in_frame, "info.channels", info.channels, "channels_in_frame", channels_in_frame, "original_frame_number", original_frame_number);
ZmqLogger::Instance()->AppendDebugMethod(
"FrameMapper::ResampleMappedAudio (adjust # of samples)",
"total_frame_samples", total_frame_samples,
"info.sample_rate", info.sample_rate,
"sample_rate_in_frame", sample_rate_in_frame,
"info.channels", info.channels,
"channels_in_frame", channels_in_frame,
"original_frame_number", original_frame_number);
// Create output frame (and allocate arrays)
AVFrame *audio_converted = AV_ALLOCATE_FRAME();
@@ -845,32 +886,39 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t orig
audio_converted->nb_samples = total_frame_samples;
av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, total_frame_samples, AV_SAMPLE_FMT_S16, 0);
ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (preparing for resample)", "in_sample_fmt", AV_SAMPLE_FMT_S16, "out_sample_fmt", AV_SAMPLE_FMT_S16, "in_sample_rate", sample_rate_in_frame, "out_sample_rate", info.sample_rate, "in_channels", channels_in_frame, "out_channels", info.channels);
ZmqLogger::Instance()->AppendDebugMethod(
"FrameMapper::ResampleMappedAudio (preparing for resample)",
"in_sample_fmt", AV_SAMPLE_FMT_S16,
"out_sample_fmt", AV_SAMPLE_FMT_S16,
"in_sample_rate", sample_rate_in_frame,
"out_sample_rate", info.sample_rate,
"in_channels", channels_in_frame,
"out_channels", info.channels);
int nb_samples = 0;
// setup resample context
if (!avr) {
avr = SWR_ALLOC();
av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
av_opt_set_int(avr, "out_channels", info.channels, 0);
av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
av_opt_set_int(avr, "out_channels", info.channels, 0);
SWR_INIT(avr);
}
// Convert audio samples
nb_samples = SWR_CONVERT(avr, // audio resample context
audio_converted->data, // output data pointers
audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
audio_frame->data, // input data pointers
audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
audio_frame->nb_samples); // number of input samples to convert
nb_samples = SWR_CONVERT(avr, // audio resample context
audio_converted->data, // output data pointers
audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
audio_frame->data, // input data pointers
audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
audio_frame->nb_samples); // number of input samples to convert
// Create a new array (to hold all resampled S16 audio samples)
int16_t* resampled_samples = new int16_t[(nb_samples * info.channels)];
@@ -889,7 +937,14 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t orig
int channel_buffer_size = nb_samples;
frame->ResizeAudio(info.channels, channel_buffer_size, info.sample_rate, info.channel_layout);
ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (Audio successfully resampled)", "nb_samples", nb_samples, "total_frame_samples", total_frame_samples, "info.sample_rate", info.sample_rate, "channels_in_frame", channels_in_frame, "info.channels", info.channels, "info.channel_layout", info.channel_layout);
ZmqLogger::Instance()->AppendDebugMethod(
"FrameMapper::ResampleMappedAudio (Audio successfully resampled)",
"nb_samples", nb_samples,
"total_frame_samples", total_frame_samples,
"info.sample_rate", info.sample_rate,
"channels_in_frame", channels_in_frame,
"info.channels", info.channels,
"info.channel_layout", info.channel_layout);
// Array of floats (to hold samples for each channel)
float *channel_buffer = new float[channel_buffer_size];
@@ -929,7 +984,10 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t orig
// Add samples to frame for this channel
frame->AddAudio(true, channel_filter, 0, channel_buffer, position, 1.0f);
ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (Add audio to channel)", "number of samples", position, "channel_filter", channel_filter);
ZmqLogger::Instance()->AppendDebugMethod(
"FrameMapper::ResampleMappedAudio (Add audio to channel)",
"number of samples", position,
"channel_filter", channel_filter);
}
// Update frame's audio meta data
@@ -957,9 +1015,10 @@ int64_t FrameMapper::AdjustFrameNumber(int64_t clip_frame_number) {
start = parent->Start();
}
// Adjust start frame and position based on parent clip. This prevents ensures the same
// frame # is used by mapped readers and clips, when calculating samples per frame. Thus,
// this prevents gaps and mismatches in # of samples.
// Adjust start frame and position based on parent clip.
// This ensures the same frame # is used by mapped readers and clips,
// when calculating samples per frame.
// Thus, this prevents gaps and mismatches in # of samples.
int64_t clip_start_frame = (start * info.fps.ToDouble()) + 1;
int64_t clip_start_position = round(position * info.fps.ToDouble()) + 1;
int64_t frame_number = clip_frame_number + clip_start_position - clip_start_frame;