diff --git a/libavformat/movenc.c b/libavformat/movenc.c index f883013b71..85b2ea9cf3 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 (Experimental, may be renamed or changed, do not use from scripts)", 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 = avpriv_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 3a729374da..21d0ee7147 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);