From c2204c579c8411771b53a4bc66324c7c5d07698a Mon Sep 17 00:00:00 2001 From: John Stebbins Date: Thu, 16 Nov 2017 14:40:12 -0800 Subject: [PATCH] movenc: add sdtp (sample dependency) box to mp4 The AppleTV 4K requires this box in order to play 2160p60 video. --- libavcodec/avcodec.h | 9 +++++++-- libavformat/movenc.c | 34 +++++++++++++++++++++++++++++++++- libavformat/movenc.h | 6 ++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 5624835023..48e9d23679 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1161,8 +1161,13 @@ typedef struct AVPacket { int64_t convergence_duration; #endif } AVPacket; -#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe -#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted +/** + * Flag is used to indicate packets that contain frames that can + * be discarded by the decoder. I.e. Non-reference frames. + */ +#define AV_PKT_FLAG_DISPOSABLE 0x0004 enum AVSideDataParamChangeFlags { AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, diff --git a/libavformat/movenc.c b/libavformat/movenc.c index a546fdfead..d263f444f4 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -227,6 +227,30 @@ static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag) return update_size(pb, pos); } +/* Sample dependency atom */ +static int mov_write_sdtp_tag(AVIOContext *pb, MOVTrack *track) +{ + int i; + uint8_t leading, dependent, reference, redundancy; + int64_t pos = avio_tell(pb); + avio_wb32(pb, 0); // size + ffio_wfourcc(pb, "sdtp"); + avio_wb32(pb, 0); // version & flags + for (i = 0; i < track->entry; i++) { + dependent = MOV_SAMPLE_DEPENDENCY_YES; + leading = reference = redundancy = MOV_SAMPLE_DEPENDENCY_UNKNOWN; + if (track->cluster[i].flags & MOV_DISPOSABLE_SAMPLE) { + reference = MOV_SAMPLE_DEPENDENCY_NO; + } + if (track->cluster[i].flags & MOV_SYNC_SAMPLE) { + dependent = MOV_SAMPLE_DEPENDENCY_NO; + } + avio_w8(pb, (leading << 6) | (dependent << 4) | + (reference << 2) | redundancy); + } + return update_size(pb, pos); +} + static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track) { avio_wb32(pb, 0x11); /* size */ @@ -1211,8 +1235,12 @@ static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra mov_write_stts_tag(pb, track); if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO || track->par->codec_tag == MKTAG('r','t','p',' ')) && - track->has_keyframes && track->has_keyframes < track->entry) + track->has_keyframes && track->has_keyframes < track->entry) { mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE); + } + if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->has_disposable) { + mov_write_sdtp_tag(pb, track); + } if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS) mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE); if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && @@ -3647,6 +3675,10 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE) trk->has_keyframes++; } + if (pkt->flags & AV_PKT_FLAG_DISPOSABLE) { + trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_SAMPLE; + trk->has_disposable++; + } trk->entry++; trk->sample_count += samples_in_chunk; mov->mdat_size += size; diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 008f4671c6..f4eb4e8078 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -51,6 +51,7 @@ typedef struct MOVIentry { int cts; #define MOV_SYNC_SAMPLE 0x0001 #define MOV_PARTIAL_SYNC_SAMPLE 0x0002 +#define MOV_DISPOSABLE_SAMPLE 0x0004 uint32_t flags; } MOVIentry; @@ -85,6 +86,7 @@ typedef struct MOVTrack { long sample_count; long sample_size; int has_keyframes; + int has_disposable; #define MOV_TRACK_CTTS 0x0001 #define MOV_TRACK_STPS 0x0002 #define MOV_TRACK_ENABLED 0x0004 @@ -180,6 +182,10 @@ typedef struct MOVMuxContext { int missing_duration_warned; } MOVMuxContext; +#define MOV_SAMPLE_DEPENDENCY_UNKNOWN 0x0 +#define MOV_SAMPLE_DEPENDENCY_YES 0x1 +#define MOV_SAMPLE_DEPENDENCY_NO 0x2 + #define FF_MOV_FLAG_RTP_HINT (1 << 0) #define FF_MOV_FLAG_FRAGMENT (1 << 1) #define FF_MOV_FLAG_EMPTY_MOOV (1 << 2) -- 2.13.6