-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
317 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#include "hdrmetadata.hpp" | ||
#include "frame.hpp" | ||
|
||
extern "C" { | ||
#include <libavutil/frame.h> | ||
#include <libavutil/hdr_dynamic_metadata.h> | ||
#include <libavutil/mastering_display_metadata.h> | ||
} | ||
|
||
namespace Ffmpeg { | ||
|
||
HdrMetaData::HdrMetaData(Frame *frame) | ||
{ | ||
auto avFrame = frame->avFrame(); | ||
auto *mdm = av_frame_get_side_data(avFrame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); | ||
auto *clm = av_frame_get_side_data(avFrame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); | ||
auto *dhp = av_frame_get_side_data(avFrame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS); | ||
|
||
if (mdm) { | ||
auto *mdmPtr = reinterpret_cast<AVMasteringDisplayMetadata *>(mdm); | ||
if (mdmPtr) { | ||
if (mdmPtr->has_luminance) { | ||
maxLuma = av_q2d(mdmPtr->max_luminance); | ||
minLuma = av_q2d(mdmPtr->min_luminance); | ||
if (maxLuma < 10.0 || minLuma >= maxLuma) { | ||
maxLuma = minLuma = 0; /* sanity */ | ||
} | ||
} | ||
if (mdmPtr->has_primaries) { | ||
primaries.red.setX(av_q2d(mdmPtr->display_primaries[0][0])); | ||
primaries.red.setY(av_q2d(mdmPtr->display_primaries[0][1])); | ||
primaries.green.setX(av_q2d(mdmPtr->display_primaries[1][0])); | ||
primaries.green.setY(av_q2d(mdmPtr->display_primaries[1][1])); | ||
primaries.blue.setX(av_q2d(mdmPtr->display_primaries[2][0])); | ||
primaries.blue.setY(av_q2d(mdmPtr->display_primaries[2][1])); | ||
primaries.white.setX(av_q2d(mdmPtr->white_point[0])); | ||
primaries.white.setY(av_q2d(mdmPtr->white_point[1])); | ||
} | ||
} | ||
} | ||
if (clm) { | ||
auto *clmPtr = reinterpret_cast<AVContentLightMetadata *>(clm); | ||
if (clmPtr) { | ||
MaxCLL = clmPtr->MaxCLL; | ||
MaxFALL = clmPtr->MaxFALL; | ||
} | ||
} | ||
if (dhp) { | ||
auto *dhpPtr = reinterpret_cast<AVDynamicHDRPlus *>(dhp); | ||
if (dhpPtr && dhpPtr->application_version < 2) { | ||
float hist_max = 0; | ||
const auto *pars = &dhpPtr->params[0]; | ||
Q_ASSERT(dhpPtr->num_windows > 0); | ||
for (int i = 0; i < 3; i++) { | ||
sceneMax[i] = 10000 * av_q2d(pars->maxscl[i]); | ||
} | ||
sceneAvg = 10000 * av_q2d(pars->average_maxrgb); | ||
|
||
// Calculate largest value from histogram to use as fallback for clips | ||
// with missing MaxSCL information. Note that this may end up picking | ||
// the "reserved" value at the 5% percentile, which in practice appears | ||
// to track the brightest pixel in the scene. | ||
for (int i = 0; i < pars->num_distribution_maxrgb_percentiles; i++) { | ||
float hist_val = av_q2d(pars->distribution_maxrgb[i].percentile); | ||
if (hist_val > hist_max) { | ||
hist_max = hist_val; | ||
} | ||
} | ||
hist_max *= 10000; | ||
if (!sceneMax[0]) { | ||
sceneMax[0] = hist_max; | ||
} | ||
if (!sceneMax[1]) { | ||
sceneMax[1] = hist_max; | ||
} | ||
if (!sceneMax[2]) { | ||
sceneMax[2] = hist_max; | ||
} | ||
|
||
if (pars->tone_mapping_flag == 1) { | ||
ootf.targetLuma = av_q2d(dhpPtr->targeted_system_display_maximum_luminance); | ||
ootf.knee.setX(av_q2d(pars->knee_point_x)); | ||
ootf.knee.setY(av_q2d(pars->knee_point_y)); | ||
assert(pars->num_bezier_curve_anchors < 16); | ||
for (int i = 0; i < pars->num_bezier_curve_anchors; i++) { | ||
ootf.anchors[i] = av_q2d(pars->bezier_curve_anchors[i]); | ||
} | ||
ootf.numAnchors = pars->num_bezier_curve_anchors; | ||
} | ||
} | ||
} | ||
} | ||
|
||
} // namespace Ffmpeg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#ifndef HDRMETADATA_HPP | ||
#define HDRMETADATA_HPP | ||
|
||
#include <QtCore> | ||
|
||
namespace Ffmpeg { | ||
|
||
class Frame; | ||
|
||
struct RawPrimaries | ||
{ | ||
QPointF red = {0, 0}, green = {0, 0}, blue = {0, 0}, white = {0, 0}; | ||
}; | ||
|
||
struct HdrBezier | ||
{ | ||
float targetLuma = 0; // target luminance (cd/m²) for this OOTF | ||
QPointF knee = {0, 0}; // cross-over knee point (0-1) | ||
float anchors[15] = {0}; // intermediate bezier curve control points (0-1) | ||
uint8_t numAnchors = 0; | ||
}; | ||
|
||
struct HdrMetaData | ||
{ | ||
public: | ||
HdrMetaData() = default; | ||
explicit HdrMetaData(Frame *frame); | ||
|
||
float minLuma = 0, maxLuma = 0; | ||
RawPrimaries primaries; | ||
|
||
unsigned MaxCLL = 0, MaxFALL = 0; | ||
|
||
float sceneMax[3] = {0}, sceneAvg = 0; | ||
HdrBezier ootf; | ||
}; | ||
|
||
} // namespace Ffmpeg | ||
|
||
#endif // HDRMETADATA_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
|
||
float luminance(vec3 color) | ||
{ | ||
return dot(color, vec3(0.2126f, 0.7152f, 0.0722f)); | ||
} | ||
|
||
float lerp(float a, float b, float t) | ||
{ | ||
return a * (1.0f - t) + b * t; | ||
} | ||
|
||
vec3 lerp(vec3 a, vec3 b, vec3 t) | ||
{ | ||
return vec3(lerp(a.x, b.x, t.x), lerp(a.y, b.y, t.y), lerp(a.z, b.z, t.z)); | ||
} | ||
|
||
vec3 reinhard(vec3 color) | ||
{ | ||
return color / (color + vec3(1.0)); | ||
} | ||
|
||
vec3 reinhard_jodie(vec3 v) | ||
{ | ||
float l = luminance(v); | ||
vec3 tv = v / (1.0f + v); | ||
return lerp(v / (1.0f + l), tv, tv); | ||
} | ||
|
||
vec3 const_luminance_reinhard(vec3 c) | ||
{ | ||
vec3 lv = vec3(0.2126f, 0.7152f, 0.0722f); | ||
vec3 nv = lv / (1.0f - lv); | ||
c /= 1.0f + dot(c, vec3(lv)); | ||
vec3 nc = vec3(max(c.x - 1.0f, 0.0f), max(c.y - 1.0f, 0.0f), max(c.z - 1.0f, 0.0f)) * nv; | ||
return c + vec3(nc.y + nc.z, nc.x + nc.z, nc.x + nc.y); | ||
} | ||
|
||
vec3 hable(vec3 color) | ||
{ | ||
float A = 0.15; | ||
float B = 0.50; | ||
float C = 0.10; | ||
float D = 0.20; | ||
float E = 0.02; | ||
float F = 0.30; | ||
return ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F; | ||
} | ||
|
||
vec3 aces(vec3 color) | ||
{ | ||
color = color * (color + 0.0245786) / (color * (0.983729 * color + 0.4329510) + 0.238081); | ||
return pow(color, vec3(1.0 / 2.2)); | ||
} | ||
|
||
vec3 filmic(vec3 color) | ||
{ | ||
color = max(vec3(0.0), color - vec3(0.004)); | ||
color = (color * (6.2 * color + 0.5)) / (color * (6.2 * color + 1.7) + 0.06); | ||
return pow(color, vec3(2.2)); | ||
} | ||
|
||
vec3 uncharted2_filmic(vec3 v) | ||
{ | ||
float exposure_bias = 2.0f; | ||
vec3 curr = hable(v * exposure_bias); | ||
|
||
vec3 W = vec3(11.2f); | ||
vec3 white_scale = vec3(1.0f) / hable(W); | ||
return curr * white_scale; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.