JPC-RR r11.7
[jpcrr.git] / streamtools / temporal-antialias.cpp
blob941523262f1b211cdf0fc4586dfd121610a106ca
1 #include "temporal-antialias.hpp"
2 #include <cmath>
3 #include <iostream>
5 framerate_reducer_temporalantialias::framerate_reducer_temporalantialias(double alpha, uint32_t n, uint32_t d)
7 double lh = log(0.5);
8 if(alpha < 0)
9 factor = log(1-exp((1 - alpha) * lh))/lh;
10 else
11 factor = alpha + 1;
12 newest = NULL;
13 last_ts = 0;
14 tdiv = 1000000000.0 * d / n;
17 framerate_reducer_temporalantialias::~framerate_reducer_temporalantialias()
19 while(!queue.empty()) {
20 delete queue.front().second;
21 queue.pop_front();
25 void framerate_reducer_temporalantialias::push(uint64_t ts, image_frame_rgbx& f)
27 if(queue.empty() && newest) {
28 delete newest;
29 newest = NULL;
31 newest = &f;
32 queue.push_back(std::make_pair(ts, newest));
35 image_frame_rgbx& framerate_reducer_temporalantialias::pull(uint64_t ts)
37 image_frame_rgbx* result;
38 if(queue.empty())
39 return *new image_frame_rgbx(0, 0); //No frame.
41 result = new image_frame_rgbx(newest->get_width(), newest->get_height());
42 size_t frames = queue.size();
43 float* weights = new float[frames];
44 float* tempframe = new float[4 * newest->get_width() * newest->get_height() + 1];
46 compute_frame_weights(ts, weights);
48 //Initialize the temporary frame.
49 for(size_t i = 0; i < 4 * newest->get_width() * newest->get_height(); i++)
50 tempframe[i] = 0;
52 //Average the frames.
53 size_t k = 0;
54 for(std::list<std::pair<uint64_t, image_frame_rgbx*> >::iterator j = queue.begin(); j != queue.end();
55 ++j, ++k) {
56 uint8_t* fpx = j->second->get_pixels();
57 for(size_t i = 0; i < 4 * newest->get_width() * newest->get_height(); i++)
58 tempframe[i] += weights[k] * fpx[i];
61 //Translate pixels back.
62 uint8_t* px = result->get_pixels();
63 for(size_t i = 0; i < 4 * newest->get_width() * newest->get_height(); i++) {
64 if(tempframe[i] < 0)
65 px[i] = 0;
66 else if(tempframe[i] > 255)
67 px[i] = 255;
68 else
69 px[i] = (uint8_t)tempframe[i];
72 //Delete all frames from queue except newest (and other temporaries).
73 delete[] weights;
74 delete[] tempframe;
75 while(true) {
76 if(queue.front().second == newest)
77 break;
78 delete queue.front().second;
79 queue.pop_front();
81 last_ts = ts;
82 return *result;
85 static double integrate_sensitivity(double fraction, double factor)
87 if(fraction < 0.5)
88 return 0.5 * pow(2 * fraction, factor);
89 else
90 return 1 - 0.5 * pow(2 - 2 * fraction, factor);
93 void framerate_reducer_temporalantialias::compute_frame_weights(uint64_t ts, float* weights)
95 size_t k = 0;
96 for(std::list<std::pair<uint64_t, image_frame_rgbx*> >::iterator j = queue.begin(); j != queue.end();
97 ++j, ++k) {
98 uint64_t start_ts = j->first;
99 //Note: The first frame needs to be processed as if its timestamp was last_ts.
100 if(j == queue.begin())
101 start_ts = last_ts;
102 //The end timestamp is timestamp of next frame or ts if there's no next frame yet.
103 std::list<std::pair<uint64_t, image_frame_rgbx*> >::iterator jn = j;
104 jn++;
105 uint64_t end_ts = ts;
106 if(jn != queue.end())
107 end_ts = jn->first;
108 double start_fraction = 1 - (start_ts - last_ts) / tdiv;
109 double end_fraction = 1 - (end_ts - last_ts) / tdiv;
110 start_fraction = (start_fraction < 0) ? 0 : (start_fraction > 1) ? 1 : start_fraction;
111 end_fraction = (end_fraction < 0) ? 0 : (end_fraction > 1) ? 1 : end_fraction;
113 weights[k] = integrate_sensitivity(start_fraction, factor) - integrate_sensitivity(end_fraction,
114 factor);
115 //std::cerr << "Weight for subframe #" << k << ": " << weights[k] << "." << std::endl;