diff options
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/movenc.c | 80 | ||||
-rw-r--r-- | libavformat/movenc.h | 1 |
2 files changed, 73 insertions, 8 deletions
diff --git a/libavformat/movenc.c b/libavformat/movenc.c index e7f4eb1d90..d7ae5f0e90 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -67,6 +67,7 @@ static const AVOption options[] = { { "dash", "Write DASH compatible fragmented MP4", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DASH}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "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" }, 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}, @@ -1499,6 +1500,66 @@ static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track) return 16; } +static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track) +{ + // Ref: https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9 + + if (track->enc->color_primaries == AVCOL_PRI_UNSPECIFIED && + track->enc->color_trc == AVCOL_TRC_UNSPECIFIED && + track->enc->colorspace == AVCOL_SPC_UNSPECIFIED) { + if ((track->enc->width >= 1920 && track->enc->height >= 1080) + || (track->enc->width == 1280 && track->enc->height == 720)) { + av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming bt709\n"); + track->enc->color_primaries = AVCOL_PRI_BT709; + } else if (track->enc->width == 720 && track->height == 576) { + av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming bt470bg\n"); + track->enc->color_primaries = AVCOL_PRI_BT470BG; + } else if (track->enc->width == 720 && + (track->height == 486 || track->height == 480)) { + av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming smpte170\n"); + track->enc->color_primaries = AVCOL_PRI_SMPTE170M; + } else { + av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, unable to assume anything\n"); + } + switch (track->enc->color_primaries) { + case AVCOL_PRI_BT709: + track->enc->color_trc = AVCOL_TRC_BT709; + track->enc->colorspace = AVCOL_SPC_BT709; + break; + case AVCOL_PRI_SMPTE170M: + case AVCOL_PRI_BT470BG: + track->enc->color_trc = AVCOL_TRC_BT709; + track->enc->colorspace = AVCOL_SPC_SMPTE170M; + break; + } + } + + avio_wb32(pb, 18); + ffio_wfourcc(pb, "colr"); + ffio_wfourcc(pb, "nclc"); + switch (track->enc->color_primaries) { + case AVCOL_PRI_BT709: avio_wb16(pb, 1); break; + case AVCOL_PRI_SMPTE170M: + case AVCOL_PRI_SMPTE240M: avio_wb16(pb, 6); break; + case AVCOL_PRI_BT470BG: avio_wb16(pb, 5); break; + default: avio_wb16(pb, 2); + } + switch (track->enc->color_trc) { + case AVCOL_TRC_BT709: avio_wb16(pb, 1); break; + case AVCOL_TRC_SMPTE170M: avio_wb16(pb, 1); break; // remapped + case AVCOL_TRC_SMPTE240M: avio_wb16(pb, 7); break; + default: avio_wb16(pb, 2); + } + switch (track->enc->colorspace) { + case AVCOL_TRC_BT709: avio_wb16(pb, 1); break; + case AVCOL_PRI_SMPTE170M: avio_wb16(pb, 6); break; + case AVCOL_PRI_SMPTE240M: avio_wb16(pb, 7); break; + default: avio_wb16(pb, 2); + } + + return 18; +} + static void find_compressor(char * compressor_name, int len, MOVTrack *track) { AVDictionaryEntry *encoder; @@ -1527,7 +1588,7 @@ static void find_compressor(char * compressor_name, int len, MOVTrack *track) } } -static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int64_t pos = avio_tell(pb); char compressor_name[32] = { 0 }; @@ -1605,6 +1666,9 @@ static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track) if (track->enc->field_order != AV_FIELD_UNKNOWN) mov_write_fiel_tag(pb, track); + if (mov->flags & FF_MOV_FLAG_WRITE_COLR) + mov_write_colr_tag(pb, track); + if (track->enc->sample_aspect_ratio.den && track->enc->sample_aspect_ratio.num && track->enc->sample_aspect_ratio.den != track->enc->sample_aspect_ratio.num) { mov_write_pasp_tag(pb, track); @@ -1695,7 +1759,7 @@ static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track) return update_size(pb, pos); } -static int mov_write_stsd_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_stsd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ @@ -1703,7 +1767,7 @@ static int mov_write_stsd_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); /* version & flags */ avio_wb32(pb, 1); /* entry count */ if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) - mov_write_video_tag(pb, track); + mov_write_video_tag(pb, mov, track); else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) mov_write_audio_tag(pb, track); else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) @@ -1807,14 +1871,14 @@ static int mov_write_dref_tag(AVIOContext *pb) return 28; } -static int mov_write_stbl_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_stbl_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int64_t pos = avio_tell(pb); int ret; avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "stbl"); - mov_write_stsd_tag(pb, track); + mov_write_stsd_tag(pb, mov, track); mov_write_stts_tag(pb, track); if ((track->enc->codec_type == AVMEDIA_TYPE_VIDEO || track->enc->codec_tag == MKTAG('r','t','p',' ')) && @@ -2032,7 +2096,7 @@ static int mov_write_hmhd_tag(AVIOContext *pb) return 28; } -static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_minf_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int64_t pos = avio_tell(pb); int ret; @@ -2057,7 +2121,7 @@ static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track) if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */ mov_write_hdlr_tag(pb, NULL); mov_write_dinf_tag(pb); - if ((ret = mov_write_stbl_tag(pb, track)) < 0) + if ((ret = mov_write_stbl_tag(pb, mov, track)) < 0) return ret; return update_size(pb, pos); } @@ -2111,7 +2175,7 @@ static int mov_write_mdia_tag(AVIOContext *pb, MOVMuxContext *mov, ffio_wfourcc(pb, "mdia"); mov_write_mdhd_tag(pb, mov, track); mov_write_hdlr_tag(pb, track); - if ((ret = mov_write_minf_tag(pb, track)) < 0) + if ((ret = mov_write_minf_tag(pb, mov, track)) < 0) return ret; return update_size(pb, pos); } diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 79027e69f3..3a729374da 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -201,6 +201,7 @@ typedef struct MOVMuxContext { #define FF_MOV_FLAG_DASH (1 << 11) #define FF_MOV_FLAG_FRAG_DISCONT (1 << 12) #define FF_MOV_FLAG_DELAY_MOOV (1 << 13) +#define FF_MOV_FLAG_WRITE_COLR (1 << 14) int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt); |