[FFmpeg-devel] [PATCH] optionally write QuickTime gama atom (was Re: Gamma function)
wm4
nfxjfg at googlemail.com
Tue Mar 3 14:05:51 CET 2015
On Tue, 3 Mar 2015 11:10:54 +0000
Kevin Wheatley <kevin.j.wheatley at gmail.com> wrote:
> From 794c8c3cf1e8506393fbcb4ddf1360042b0fc82f Mon Sep 17 00:00:00 2001
> From: Kevin Wheatley <kevin.j.wheatley at gmail.com>
> Date: Mon, 2 Mar 2015 12:50:53 +0000
> Subject: [PATCH] Add 'gama' atom for .mov only, reuses pngenc.c gamma values by sharing
> function in new color_utils.[ch] file.
>
> Use lrint() instead of round()
>
> Signed-off-by: Kevin Wheatley <kevin.j.wheatley at gmail.com>
> ---
> libavcodec/pngenc.c | 29 +++----------------------
> libavformat/movenc.c | 35 +++++++++++++++++++++++++++++++
> libavformat/movenc.h | 2 +
> libavutil/Makefile | 2 +
> libavutil/color_utils.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++
> libavutil/color_utils.h | 29 ++++++++++++++++++++++++++
> 6 files changed, 124 insertions(+), 25 deletions(-)
> create mode 100644 libavutil/color_utils.c
> create mode 100644 libavutil/color_utils.h
>
> diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c
> index 4e67ce2..fddcca4 100644
> --- a/libavcodec/pngenc.c
> +++ b/libavcodec/pngenc.c
> @@ -28,6 +28,7 @@
> #include "libavutil/avassert.h"
> #include "libavutil/libm.h"
> #include "libavutil/opt.h"
> +#include "libavutil/color_utils.h"
>
> #include <zlib.h>
>
> @@ -277,31 +278,9 @@ static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf)
>
> static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf)
> {
> - double gamma;
> - switch (trc) {
> - case AVCOL_TRC_BT709:
> - case AVCOL_TRC_SMPTE170M:
> - case AVCOL_TRC_SMPTE240M:
> - case AVCOL_TRC_BT1361_ECG:
> - case AVCOL_TRC_BT2020_10:
> - case AVCOL_TRC_BT2020_12:
> - /* these share a segmented TRC, but gamma 1.961 is a close
> - approximation, and also more correct for decoding content */
> - gamma = 1.961;
> - break;
> - case AVCOL_TRC_GAMMA22:
> - case AVCOL_TRC_IEC61966_2_1:
> - gamma = 2.2;
> - break;
> - case AVCOL_TRC_GAMMA28:
> - gamma = 2.8;
> - break;
> - case AVCOL_TRC_LINEAR:
> - gamma = 1.0;
> - break;
> - default:
> - return 0;
> - }
> + double gamma = get_gamma_from_trc(trc);
> + if (gamma <= 1e-6)
> + return 0;
>
> AV_WB32_PNG(buf, 1.0 / gamma);
> return 1;
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index e496ba4..7c10d0e 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -40,10 +40,12 @@
> #include "libavutil/avstring.h"
> #include "libavutil/intfloat.h"
> #include "libavutil/mathematics.h"
> +#include "libavutil/libm.h"
> #include "libavutil/opt.h"
> #include "libavutil/dict.h"
> #include "libavutil/pixdesc.h"
> #include "libavutil/timecode.h"
> +#include "libavutil/color_utils.h"
> #include "hevc.h"
> #include "rtpenc.h"
> #include "mov_chan.h"
> @@ -65,6 +67,7 @@ static const AVOption options[] = {
> { "frag_discont", "Signal that the next fragment is discontinuous from earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
> { "delay_moov", "Delay writing the initial moov until the first fragment is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
> { "write_colr", "Write colr atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
> + { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
> FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
> { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
> { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
> @@ -77,6 +80,7 @@ static const AVOption options[] = {
> { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
> { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
> { "fragment_index", "Fragment number of the next fragment", offsetof(MOVMuxContext, fragments), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
> + { "mov_gamma", "gamma value for gama atom", offsetof(MOVMuxContext, gamma), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, 0.0, 10, AV_OPT_FLAG_ENCODING_PARAM},
> { NULL },
> };
>
> @@ -1519,6 +1523,31 @@ static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
> return 16;
> }
>
> +static int mov_write_gama_tag(AVIOContext *pb, MOVTrack *track, double gamma)
> +{
> + uint32_t gama = 0;
> + if (gamma <= 0.0)
> + {
> + gamma = get_gamma_from_trc(track->enc->color_trc);
> + }
> + av_log(pb, AV_LOG_DEBUG, "gamma value %g\n", gamma);
> +
> + if (gamma > 1e-6) {
> + gama = (uint32_t)lrint((double)(1<<16) * gamma);
> + av_log(pb, AV_LOG_DEBUG, "writing gama value %d\n", gama);
> +
> + av_assert0(track->mode == MODE_MOV);
> + avio_wb32(pb, 12);
> + ffio_wfourcc(pb, "gama");
> + avio_wb32(pb, gama);
> + return 12;
> + }
> + else {
> + av_log(pb, AV_LOG_WARNING, "gamma value unknown, unable to write gama atom\n");
> + }
> + return 0;
> +}
> +
> static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track)
> {
> // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
> @@ -1700,6 +1729,12 @@ static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr
> if (track->enc->field_order != AV_FIELD_UNKNOWN)
> mov_write_fiel_tag(pb, track);
>
> + if (mov->flags & FF_MOV_FLAG_WRITE_GAMA) {
> + if (track->mode == MODE_MOV)
> + mov_write_gama_tag(pb, track, mov->gamma);
> + else
> + av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n");
> + }
> if (mov->flags & FF_MOV_FLAG_WRITE_COLR) {
> if (track->mode == MODE_MOV || track->mode == MODE_MP4)
> mov_write_colr_tag(pb, track);
> diff --git a/libavformat/movenc.h b/libavformat/movenc.h
> index 3a72937..21d0ee7 100644
> --- a/libavformat/movenc.h
> +++ b/libavformat/movenc.h
> @@ -185,6 +185,7 @@ typedef struct MOVMuxContext {
> AVFormatContext *fc;
>
> int use_editlist;
> + float gamma;
> } MOVMuxContext;
>
> #define FF_MOV_FLAG_RTP_HINT (1 << 0)
> @@ -202,6 +203,7 @@ typedef struct MOVMuxContext {
> #define FF_MOV_FLAG_FRAG_DISCONT (1 << 12)
> #define FF_MOV_FLAG_DELAY_MOOV (1 << 13)
> #define FF_MOV_FLAG_WRITE_COLR (1 << 14)
> +#define FF_MOV_FLAG_WRITE_GAMA (1 << 15)
>
> int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);
>
> diff --git a/libavutil/Makefile b/libavutil/Makefile
> index 6caf896..ca20539 100644
> --- a/libavutil/Makefile
> +++ b/libavutil/Makefile
> @@ -18,6 +18,7 @@ HEADERS = adler32.h \
> cast5.h \
> camellia.h \
> channel_layout.h \
> + color_utils.h \
> common.h \
IMO this header shouldn't be public, at least not yet. And I think
adding them to HEADERS will install the header. (Not sure about how
this works.)
> cpu.h \
> crc.h \
> @@ -88,6 +89,7 @@ OBJS = adler32.o \
> cast5.o \
> camellia.o \
> channel_layout.o \
> + color_utils.o \
> cpu.o \
> crc.o \
> des.o \
> diff --git a/libavutil/color_utils.c b/libavutil/color_utils.c
> new file mode 100644
> index 0000000..a4d75a5
> --- /dev/null
> +++ b/libavutil/color_utils.c
> @@ -0,0 +1,52 @@
> +/*
> + * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley at gmail.com>
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include "libavutil/color_utils.h"
> +#include "libavutil/pixfmt.h"
> +
> +double get_gamma_from_trc(enum AVColorTransferCharacteristic trc)
Public API functions must start with "av_". API functions which are
private to FFmpeg, but are used across the sub-libs (e.g. libavcodec
using a private libavutil function) must start with "avpriv_".
> +{
> + double gamma;
> + switch (trc) {
> + case AVCOL_TRC_BT709:
> + case AVCOL_TRC_SMPTE170M:
> + case AVCOL_TRC_SMPTE240M:
> + case AVCOL_TRC_BT1361_ECG:
> + case AVCOL_TRC_BT2020_10:
> + case AVCOL_TRC_BT2020_12:
> + /* these share a segmented TRC, but gamma 1.961 is a close
> + approximation, and also more correct for decoding content */
> + gamma = 1.961;
> + break;
> + case AVCOL_TRC_GAMMA22:
> + case AVCOL_TRC_IEC61966_2_1:
> + gamma = 2.2;
> + break;
> + case AVCOL_TRC_GAMMA28:
> + gamma = 2.8;
> + break;
> + case AVCOL_TRC_LINEAR:
> + gamma = 1.0;
> + break;
> + default:
> + gamma = 0.0;
Is this really a sane default? Or is it some placeholder value (i.e.
"not valid")?
> + }
> + return gamma;
> +}
> diff --git a/libavutil/color_utils.h b/libavutil/color_utils.h
> new file mode 100644
> index 0000000..f70d906
> --- /dev/null
> +++ b/libavutil/color_utils.h
> @@ -0,0 +1,29 @@
> +/*
> + * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley at gmail.com>
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef AVUTIL_COLOR_UTILS_H
> +#define AVUTIL_COLOR_UTILS_H
> +
> +
> +#include "libavutil/pixfmt.h"
> +
> +double get_gamma_from_trc(enum AVColorTransferCharacteristic trc);
Lacks doxygen documentation.
> +
> +#endif
More information about the ffmpeg-devel
mailing list