Skip to content

Commit

Permalink
修改 shader 生成;
Browse files Browse the repository at this point in the history
  • Loading branch information
RealChuan committed Nov 17, 2023
1 parent e7e7bbd commit a94a6c0
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 43 deletions.
2 changes: 2 additions & 0 deletions ffmpeg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ set(PROJECT_SOURCES
formatcontext.h
frame.cc
frame.hpp
hdrmetadata.cc
hdrmetadata.hpp
mediainfo.cc
mediainfo.hpp
packet.cpp
Expand Down
2 changes: 2 additions & 0 deletions ffmpeg/ffmpeg.pro
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ SOURCES += \
ffmpegutils.cc \
formatcontext.cpp \
frame.cc \
hdrmetadata.cc \
mediainfo.cc \
packet.cpp \
player.cpp \
Expand Down Expand Up @@ -57,6 +58,7 @@ HEADERS += \
ffmpegutils.hpp \
formatcontext.h \
frame.hpp \
hdrmetadata.hpp \
mediainfo.hpp \
packet.h \
player.h \
Expand Down
94 changes: 94 additions & 0 deletions ffmpeg/hdrmetadata.cc
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
40 changes: 40 additions & 0 deletions ffmpeg/hdrmetadata.hpp
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
41 changes: 33 additions & 8 deletions ffmpeg/videorender/openglshader.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "openglshader.hpp"
#include "hdrmetadata.hpp"
#include "shaderutils.hpp"

#include <ffmpeg/frame.hpp>
Expand All @@ -19,7 +20,26 @@ class OpenglShader::OpenglShaderPrivate
: q_ptr(q)
{}

void init(Frame *frame)
{
auto *avFrame = frame->avFrame();
srcHdrMetaData = HdrMetaData(frame);
if (!srcHdrMetaData.maxLuma) {
srcHdrMetaData.maxLuma = ShaderUtils::trcNomPeak(avFrame->color_trc) * MP_REF_WHITE;
}
dstColorTrc = avFrame->color_trc;
if (dstColorTrc == AVCOL_TRC_LINEAR || ShaderUtils::trcIsHdr(dstColorTrc)) {
dstColorTrc = AVCOL_TRC_GAMMA22;
}
dstHdrMetaData.maxLuma = ShaderUtils::trcNomPeak(dstColorTrc) * MP_REF_WHITE;
}

OpenglShader *q_ptr;

HdrMetaData srcHdrMetaData;
HdrMetaData dstHdrMetaData;

AVColorTransferCharacteristic dstColorTrc;
};

OpenglShader::OpenglShader(QObject *parent)
Expand All @@ -31,25 +51,30 @@ OpenglShader::~OpenglShader() = default;

auto OpenglShader::generate(Frame *frame) -> QByteArray
{
d_ptr->init(frame);

auto *avFrame = frame->avFrame();
auto format = avFrame->format;

qInfo() << "Generate Shader:" << format;
auto frag = ShaderUtils::header();
auto header = ShaderUtils::header();
QByteArray frag("\nvoid main() {\n");
if (!ShaderUtils::beginFragment(frag, format)) {
return {};
}
ShaderUtils::passLinearize(frag, avFrame->color_trc);

auto temp = QString("color.rgb *= vec3(%1);\n").arg(ShaderUtils::trcNomPeak(avFrame->color_trc));
frag.append(temp.toUtf8());
ShaderUtils::passGama(frag, avFrame->color_trc);
//ShaderUtils::passOotf(frag, d_ptr->srcHdrMetaData.maxLuma, avFrame->color_trc);

// HDR
// ShaderUtils::toneMap(frag, avFrame);
ShaderUtils::toneMap(header, frag);

auto color_trc = ShaderUtils::trcIsHdr(avFrame->color_trc) ? AVCOL_TRC_GAMMA22
: avFrame->color_trc;
ShaderUtils::passDeLinearize(frag, color_trc);
//ShaderUtils::passInverseOotf(frag, d_ptr->dstHdrMetaData.maxLuma, avFrame->color_trc);
ShaderUtils::passDeGama(frag, d_ptr->dstColorTrc);
ShaderUtils::passDeLinearize(frag, d_ptr->dstColorTrc);
ShaderUtils::finishFragment(frag);
frag.append("\n}\n");
frag = header + "\n" + frag;
ShaderUtils::printShader(frag);
return frag;
}
Expand Down
70 changes: 70 additions & 0 deletions ffmpeg/videorender/shader/tonemap.frag
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;
}
2 changes: 1 addition & 1 deletion ffmpeg/videorender/shader/video_color.frag
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ vec3 adjustSaturation(vec3 rgb, float saturation) // 调整饱和度
vec3 hsv = rgb2Hsv(rgb);
hsv.y = hsv.y * saturation;
return hsv2Rgb(hsv);
}
}
1 change: 1 addition & 0 deletions ffmpeg/videorender/shaders.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
<file>shader/video_color.frag</file>
<file>shader/video_header.frag</file>
<file>shader/video_p010le.frag</file>
<file>shader/tonemap.frag</file>
</qresource>
</RCC>
Loading

0 comments on commit a94a6c0

Please sign in to comment.