mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-02-15 11:17:49 +00:00
avformat/movenc: Add simplistic 'colr' tag writing support to mov container
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
b8f3b0703c
commit
7b6f419176
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -37,11 +37,15 @@ fate-vsynth%-dnxhd-720p-10bit: ENCOPTS = -s hd720 -b 90M \
|
||||
-pix_fmt yuv422p10 -frames 5 -qmax 8
|
||||
fate-vsynth%-dnxhd-720p-10bit: FMT = dnxhd
|
||||
|
||||
FATE_VCODEC-$(call ENCDEC, DNXHD, MOV) += dnxhd-1080i
|
||||
FATE_VCODEC-$(call ENCDEC, DNXHD, MOV) += dnxhd-1080i dnxhd-1080i-colr
|
||||
fate-vsynth%-dnxhd-1080i: ENCOPTS = -s hd1080 -b 120M -flags +ildct \
|
||||
-pix_fmt yuv422p -frames 5 -qmax 8
|
||||
fate-vsynth%-dnxhd-1080i: FMT = mov
|
||||
|
||||
fate-vsynth%-dnxhd-1080i-colr: ENCOPTS = -s hd1080 -b 120M -flags +ildct -movflags write_colr \
|
||||
-pix_fmt yuv422p -frames 5 -qmax 8
|
||||
fate-vsynth%-dnxhd-1080i-colr: FMT = mov
|
||||
|
||||
FATE_VCODEC-$(call ENCDEC, DVVIDEO, DV) += dv dv-411 dv-50
|
||||
fate-vsynth%-dv: CODEC = dvvideo
|
||||
fate-vsynth%-dv: ENCOPTS = -dct int -s pal
|
||||
|
4
tests/ref/vsynth/vsynth1-dnxhd-1080i-colr
Normal file
4
tests/ref/vsynth/vsynth1-dnxhd-1080i-colr
Normal file
@ -0,0 +1,4 @@
|
||||
b6fbfdfe7027fde6853930abad87eaab *tests/data/fate/vsynth1-dnxhd-1080i-colr.mov
|
||||
3031929 tests/data/fate/vsynth1-dnxhd-1080i-colr.mov
|
||||
a09132c6db44f415e831dcaa630a351b *tests/data/fate/vsynth1-dnxhd-1080i-colr.out.rawvideo
|
||||
stddev: 6.29 PSNR: 32.15 MAXDIFF: 64 bytes: 7603200/ 760320
|
4
tests/ref/vsynth/vsynth2-dnxhd-1080i-colr
Normal file
4
tests/ref/vsynth/vsynth2-dnxhd-1080i-colr
Normal file
@ -0,0 +1,4 @@
|
||||
d510bc0d58c7cae875e3e67023771d6f *tests/data/fate/vsynth2-dnxhd-1080i-colr.mov
|
||||
3031929 tests/data/fate/vsynth2-dnxhd-1080i-colr.mov
|
||||
099001db73036eeb9545c463cf90f0ba *tests/data/fate/vsynth2-dnxhd-1080i-colr.out.rawvideo
|
||||
stddev: 1.53 PSNR: 44.43 MAXDIFF: 31 bytes: 7603200/ 760320
|
4
tests/ref/vsynth/vsynth3-dnxhd-1080i-colr
Normal file
4
tests/ref/vsynth/vsynth3-dnxhd-1080i-colr
Normal file
@ -0,0 +1,4 @@
|
||||
3b06d8675f9623db77b6a42916663608 *tests/data/fate/vsynth3-dnxhd-1080i-colr.mov
|
||||
3031929 tests/data/fate/vsynth3-dnxhd-1080i-colr.mov
|
||||
382fc519604abb5d87071bdce013cef9 *tests/data/fate/vsynth3-dnxhd-1080i-colr.out.rawvideo
|
||||
stddev: 7.81 PSNR: 30.28 MAXDIFF: 61 bytes: 86700/ 8670
|
4
tests/ref/vsynth/vsynth_lena-dnxhd-1080i-colr
Normal file
4
tests/ref/vsynth/vsynth_lena-dnxhd-1080i-colr
Normal file
@ -0,0 +1,4 @@
|
||||
4deae1b3d9a5c8fbd28075e8dca0034e *tests/data/fate/vsynth_lena-dnxhd-1080i-colr.mov
|
||||
3031929 tests/data/fate/vsynth_lena-dnxhd-1080i-colr.mov
|
||||
744ba46da5d4c19a28562ea31061d170 *tests/data/fate/vsynth_lena-dnxhd-1080i-colr.out.rawvideo
|
||||
stddev: 1.31 PSNR: 45.77 MAXDIFF: 23 bytes: 7603200/ 760320
|
Loading…
Reference in New Issue
Block a user